Search code examples
djangodjango-formsdjango-widget

In Django how can I get a widget that accepts an ISO 8601 datetime string and works with a DateTimeField?


I want to submit an ISO 8601 datetime string with a time zone designator to a django form that I am writing. I want to use a standard DateTimeField for the datetime but have a widget that accepts such a datetime string. Is this possible, or am I confused about the relationship between Widgets and Fields? How do I do it?


Parsing the string is easy, using django.utils.datepase.parse_datetime.

I have tried writing a widget like so:

from django.forms import HiddenInput
from django.utils.dateparse import parse_datetime

class DateTimeInputForMachines(HiddenInput):
    def _format_value(self, value):
        out = super(DateTimeInputForMachines, self)._format_value(parse_datetime(value))
        return out

and using it in a ModelForm like so:

from mywidgets import DateTimeInputForMachines

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['start', 'thing']

        widgets = {
            'start': DateTimeInputForMachines()
        }

but the 'start' field fails validation with "Enter a valid date/time."


Solution

  • Widgets are for displaying data, and have nothing to do with validation.

    If you just need to input a custom date format, there is no need for any subclassing; you can supply input_formats directly on the field (see the documentation).

    class MyForm(forms.ModelForm):
        start = forms.DateTimeField(input_formats=["%Y-%m-%dT%H:%M:%S.%z"])
    
        class Meta:
            model = MyModel
            fields = ['start', 'thing']