1

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

BudgieInWA
  • 2,184
  • 1
  • 17
  • 31

1 Answers1

3

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']
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I was under the impression that `input_formats` wouldn't suffice for such string (from https://code.djangoproject.com/ticket/11385 and others). Will it work with "2015-09-08T01:55:28+08:00" or will I need to convert to UTC first? I'll try it when I next get the chance. – BudgieInWA Sep 10 '15 at 09:59
  • 2
    That is a 5-year-old ticket, which refers to a Python bug which has since been fixed. It turns out though that in Python 2.7 whether `%z` works depends on your system. In Python 3.2+ it will always work. – Daniel Roseman Sep 10 '15 at 10:54
  • Thanks. I tested it and this is the way to go. It's not perfect because it turns out python's `%z` is of the form `+0800` instead of `+08:00` which is a pain. – BudgieInWA Sep 11 '15 at 05:44