Login

Natural language date/time form fields

Author:
jdriscoll
Posted:
June 7, 2007
Language:
Python
Version:
.96
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

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 2 weeks ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 10 months, 1 week ago
  5. Help text hyperlinks by sa2812 11 months ago

Comments

gsf0 (on December 12, 2008):

Also need "from datetime import datetime". Thanks for the example!

#

gsf0 (on December 12, 2008):

Oh, also, with the SplitDateTimeWidget I needed to change it to parser.parse(' '.join(value)).

#

gsf0 (on December 12, 2008):

Or, in keeping with the code in django.forms.fields, I could include:

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)

#

Please login first before commenting.