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.
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:
try:
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_element.DatePicker({
format:'d-m-Y',
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.
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.