#33100 closed New feature (duplicate)
Add a DateInput widget that provides a date picker via the HTML <input style="date"> element
Reported by: | dennisvang | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 3.2 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
To support this request, consider that the StackOverflow question Using Django time/date widgets in custom form gets an average of almost 10k views each year (which is a lot).
Background
The forms.DateField
uses a forms.widgets.DateInput widget, which renders as a standard <input style="text">
in HTML (a simple text box).
It would be very convenient if this widget could provide a date picker by default, similar to date fields on the Django admin site, for example.
There are several options here:
- One could use the forms.widgets.SelectDateWidget, but that is not as convenient as a proper calendar date picker.
- One could use the Django admin date (and/or time) widgets, but, as far as I know, the admin widgets are not part of the public API, and getting them to work can be a puzzle.
- There are also third-party apps that implement date pickers, but those introduce additional dependencies.
- Last, but not least, modern browsers support the HTML `<input style="date">` element, which provides a very clean solution to the problem described above, without any custom CSS or JavaScript.
Although it is not too difficult to implement a custom widget that uses <input style="date">
, one would need to know about it existence first.
Feature request
Would it be possible to provide something like a forms.widgets.BrowserDateInput
that leverages <input style="date">
?
A crude implementation could look like this:
class BrowserDateInput(forms.widgets.DateInput): def get_context(self, name, value, attrs): context = super().get_context(name, value, attrs) context['widget']['type'] = 'date' return context
To set current date and/or minimum/maximum allowable date, we can use the attrs
argument. For example:
BrowserDateInput(attrs=dict(value=self.today, min=self.today))
Note that the browser automatically takes care of client-side field validation.
P.S. a similar request could be made for a BrowserTimeInput
, although localization could complicate matters here (haven't looked into that yet).
Change History (9)
comment:1 by , 3 years ago
Summary: | Request for a DateInput class that provides a date picker via the HTML <input style="date"> element → Request for a DateInput widget that provides a date picker via the HTML <input style="date"> element |
---|
comment:2 by , 3 years ago
Summary: | Request for a DateInput widget that provides a date picker via the HTML <input style="date"> element → Add a DateInput widget that provides a date picker via the HTML <input style="date"> element |
---|
comment:3 by , 3 years ago
Description: | modified (diff) |
---|
follow-up: 5 comment:4 by , 3 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
comment:5 by , 3 years ago
Replying to Tim Graham:
Duplicate of #21470. If the concerns there are no longer an issue, we could reopen that ticket.
Although I am not quite sure if the concerns from that ticket (or from 16630) are still valid (they were raised ten years ago), to my untrained eye browser support for `<input style="date">` looks pretty solid now.
Regardless, my proposal is not to modify the existing DateInput
, but rather to introduce a new widget called e.g. BrowserDateInput
.
- this circumvents any backward compatibility issues
- the class name gives a clear indication of what the new widget does
- looks like a relatively minor effort, which could nevertheless be of great help to many people (considering the number of related questions on the web).
It would be great if this ticket could be re-opened. :-)
comment:6 by , 3 years ago
I doubt there would be consensus to add unused widgets in Django, especially when the implementation is so trivial:
from django import forms class DateInput(forms.DateInput): input_type = 'date'
or even: DateInput(attrs={'type': 'date'})
but you could write to the DevelopersMailingList to reach a wider audience.
follow-up: 8 comment:7 by , 3 years ago
I think it would be interesting to complete the DateInput
documentation explaining that and giving the small code excerpt given by Tim.
comment:8 by , 3 years ago
Replying to Claude Paroz:
I think it would be interesting to complete the
DateInput
documentation explaining that and giving the small code excerpt given by Tim.
I agree.
The implementation is indeed trivial, as Tim Graham's example proves.
However, one cannot implement something that one does not know about.
Therefore, I think an example in the documentation would be very helpful.
comment:9 by , 2 years ago
It should be noted that just changing the type attribute is not all you need to do in order to use the date and time inputs correctly within Django. Whilst doing that will render the HTML input it will not pickup the initial values correctly as you need to format them into the right input format, normally by using isoformat() on either the initial or instance value depending on whether you are using a standard form or model form.
The "datetime-local" input will work okay without any other changes.
For the sake of anyone coming back to this ticket in the future here's one way of subclassing the DateInput and TimeInput widgets with the updated render method that will mean you can then use these as you would standard widgets and won't hit the issues described above
class DateInputPicker(DateInput): input_type = "date" def render(self, name, value, attrs=None, renderer=None): """Render the widget as an HTML string.""" value = value.isoformat() if value and isinstance(value, date) else value context = self.get_context(name, value, attrs) return self._render(self.template_name, context, renderer) class TimeInputPicker(TimeInput): input_type = "time" def render(self, name, value, attrs=None, renderer=None): """Render the widget as an HTML string.""" value = value.isoformat() if value and isinstance(value, date) else value context = self.get_context(name, value, attrs) return self._render(self.template_name, context, renderer)
Duplicate of #21470. If the concerns there are no longer an issue, we could reopen that ticket.