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

0 Comments

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.

magnetic-boy-Ivan-Stoiljkovic-1
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.

01.class EventForm(forms.ModelForm):  
02.class Meta:   
03.model = Event   
04.fields = ('title', 'details', 'when')   
05.     
06.title = forms.CharField(required = False)   
07.details = forms.CharField(widget = forms.Textarea()   
08.<strong>when = forms.CharField(min_length = 10, widget = DateInput(format="%d-%m-%Y"))</strong>   
09.     
10.def clean_when(self):   
11.when = self.cleaned_data.get('when')   
12.     
13.if when:   
14.try:   
15.when = datetime.datetime.strptime(when, '%d-%m-%Y')   
16.except ValueError:   
17.when = None   
18.self._errors['when'] = ['Invalid date selected.']   
19.     
20.return when

That's the form done.

Now to set up the date picker widget.

Import the CSS and JS files.

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

To set up the date picker:

01.var date_element = $('#id_when');  
02.     
03.date_element.DatePicker({   
04.format:'d-m-Y',   
05.date: date_str,   
06.onBeforeShow: function(){   
07.date_element.DatePickerSetDate(date_element.val(), true);   
08.}   
09.});

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.

 

Source

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