Opened 3 years ago

Closed 3 years ago

Last modified 20 months ago

#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 dennisvang)

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 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.

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 dennisvang, 3 years ago

Summary: Request for a DateInput class that provides a date picker via the HTML <input style="date"> elementRequest for a DateInput widget that provides a date picker via the HTML <input style="date"> element

comment:2 by dennisvang, 3 years ago

Summary: Request for a DateInput widget that provides a date picker via the HTML <input style="date"> elementAdd a DateInput widget that provides a date picker via the HTML <input style="date"> element

comment:3 by dennisvang, 3 years ago

Description: modified (diff)

comment:4 by Tim Graham, 3 years ago

Resolution: duplicate
Status: newclosed

Duplicate of #21470. If the concerns there are no longer an issue, we could reopen that ticket.

in reply to:  4 comment:5 by dennisvang, 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. (Support for datetime(-local) mentioned in #16630 is still not ideal, but my proposal only concerns style="date").

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. :-)

Last edited 3 years ago by dennisvang (previous) (diff)

comment:6 by Tim Graham, 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.

comment:7 by Claude Paroz, 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.

in reply to:  7 comment:8 by dennisvang, 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.

in reply to:  description comment:9 by Steven Mapes, 20 months 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)
Note: See TracTickets for help on using tickets.
Back to Top