Login

Natural language date/time form fields

Author:
jdriscoll
Posted:
June 7, 2007
Language:
Python
Version:
.96
Tags:
newforms datetime date
Score:
5 (after 5 ratings)

Form fields use the dateutil module http://labix.org/python-dateutil to parse natural-language input for date and datetime fields.

The callback function will replace all date and datetime fields automatically for form_for_model and form_for_instance. Note: by replacing the 'form_class' keyword argument instead of just returning the field itself you preserve the 'required' status of the field.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from dateutil import parser

class ParseDateTimeField(forms.Field):
    """ DateTime field that accepts natural-language input

    Uses the DateUtil module to parse input.

    """
    def clean(self, value):
        super(ParseDateTimeField, self).clean(value)
        if value in (None, ''):
            return None
        if isinstance(value, datetime):
            return value
        try:
            return parser.parse(value)
        except ValueError:
            raise ValidationError(u'Enter a valid date and time')


class ParseDateField(forms.Field):
    """ Date field that accepts natural-language input

    Uses the DateUtil module to parse input.

    """
    def clean(self, value):
        super(ParseDateField, self).clean(value)
        if value in (None, ''):
            return None
        if isinstance(value, datetime):
            return value
        try:
            return parser.parse(value).date()
        except ValueError:
            raise ValidationError(u'Enter a valid date')

def parsefield_callback(field, **kwargs):
    """ Replace standard DateField and DateTimeField with parsing variants """
    if isinstance(field, models.DateTimeField):
        kwargs.update({'form_class': ParseDateTimeField})
    elif isinstance(field, models.DateField):
        kwargs.update({'form_class': ParseDateField})
    return field.formfield(**kwargs)

MyForm = forms_for_model(MyModel, formfield_callback=parsefield_callback)

More like this

Comments

gsf0 (on December 12, 2008):
<p>Also need "from datetime import datetime". Thanks for the example!</p>

#

gsf0 (on December 12, 2008):
<p>Oh, also, with the SplitDateTimeWidget I needed to change it to parser.parse(' '.join(value)).</p>

#

gsf0 (on December 12, 2008):
<p>Or, in keeping with the code in django.forms.fields, I could include:</p> <pre>if isinstance(value, list): # Input comes from a SplitDateTimeWidget, for example. So, it's two # components: date and time. if len(value) != 2: raise ValidationError(self.error_messages['invalid']) value = '%s %s' % tuple(value) </pre>

#

Please login first before commenting.