django: Date time picker on a custom form without undocumented hacks or importing admin files

The problem

I tried using the forms.DateTimeField and forms.DateField in my form and it kept coming up with "Enter a valid date/time.", despite the fact I given the custom "input_formats" in the constructor.

Most of the search results bring you back to a post on StackOverflow called "Using Django time/date widgets in custom form". It's basically reusing the JS widget that you can access in the admin and it works really well.

But personally I'm not a fan of this method. You'll have to use some undocumented features and import a whole stack of Django admin CSS/JS files on every page you need the date picker.

For security sake, I tend to keep public and admin CSS/JS files separate.

We'll fix this chump up!

The Theory

The way which I implemented this involves use of a 3rd party Javascript date picker of your choice. This way you get to fully customise the selection.

I prefer to eyecon's datepicker, which allows for some pretty neat customisation. I especially like how they made it incredibly easy to pick the month/year. It is much smaller compared to jQueryUI datepicker.

In Practice

The main thing is to change the form field to a CharField.

class EventForm(forms.ModelForm):
class Meta:
model = Event
fields = ('title', 'details', 'when')

title = forms.CharField(required = False)
details = forms.CharField(widget = forms.Textarea()
when = forms.CharField(min_length = 10, widget = DateInput(format="%d-%m-%Y"))

def clean_when(self):
when = self.cleaned_data.get('when')

if when:
when = datetime.datetime.strptime(when, '%d-%m-%Y')
except ValueError:
when = None
self._errors['when'] = ['Invalid date selected.']

return when

That's the form done.

Now to set up the date picker widget.

Import the CSS and JS files.

<link rel="stylesheet" media="screen" type="text/css" href="{{ MEDIA_URL }}datepicker.css" />
<script type="text/javascript" src="{{ MEDIA_URL }}datepicker.js"></script>

To set up the date picker:

var date_element = $('#id_when');

date: date_str,
onBeforeShow: function(){
date_element.DatePickerSetDate(date_element.val(), true);

That's it! See the date picker documentation for more options, but that's more than enough to get you up and running.

Magneto Kid
Now you're badass!

Custom initial date format

*update 23/6/2011*

Oops, forgot something. If your Django system time format differs to the format you want to use on your Javascript date picker, you'll have to tweak the CharField() a little to include the DateInput() widget.



Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog