When working with forms in Django it can be awkward or even difficult to capture dates in standard form fields. Fortunately Django supports a simple date picker to make this much easier. Even better we can do this without additional CSS or Javascript!
We can add a date picker to our form fields by using the DateInput
widget already built into Django. In the tutorial below we will go over the major steps required to get this date picker working in your Django application.
Let's first look at our HTML template. Our end goal is to populate the {{ form }}
variable with our model form fields and render the HTML in a browser. The HTML action
attribute specifies the URL to send the form data to when submitted. In our example we will send form data to /my-form-submit-page/
(not implemented in this tutorial).
The csrf_token
template tag seen below is used for cross site request forgery protection. See here for more details.
Here is the task_form.html
template containing our HTML form.
<!-- task_form.html -->
<h1>My Task Form</h1>
<form action="/my-form-submit-page/" method="post">
{% csrf_token %}
{{ form }}
<button type="submit" class="">Save</button>
</form>
Let's create the Task
model to use with our form. In this tutorial our form fields will match the fields in the model. Notice this model contains a DateTimeField
. This is the field we will populate with our datepicker.
Here is the models.py
containing our model logic.
# models.py
from django.db import models
class Task(models.Model):
name = models.CharField(max_length=255)
target_date = models.DateTimeField()
Next let's implement the Django form logic. There are many ways to do this, but for simplicity we will extend the built-in ModelForm
class.
Our form class is where we can override field defaults using a widget. To do this we use the widgets
attribute of the inner Meta
class. Django expects this attribute to contain a dictionary which maps field names to widget classes or instances. In the example below, we map the target_date
field to the DateInput
widget.
Here is the forms.py
containing our form logic.
# forms.py
from django.forms import ModelForm, widgets
from .models import Task
class TaskForm(ModelForm):
class Meta:
model = Task
fields = [
'name',
'target_date'
]
widgets = {
'target_date': widgets.DateInput(attrs={'type': 'date'})
}
Our view is responsible for populating the {{ form }}
variable in our HTML template. There are many ways to acheive this in Django, but for simplicity we will extend the built-in FormView
class. Here we can specify our HTML template task_form.html
and our form class TaskForm
.
Here is the views.py
containing our view logic.
# views.py
from django.views.generic.edit import FormView
from .forms import TaskForm
class TaskFormView(FormView):
template_name = "task_form.html"
form_class = TaskForm
We also need to map our view in our urls.py
file. In our example we map our form to the task-form/
path.
# urls.py
from django.urls import path
from datepicker.views import TaskFormView
urlpatterns = [
path('task-form/', TaskFormView.as_view()),
]
With all of the above set up in our Django project we can now navigate to the task-form/
URL and use the date picker with our target_date
field!