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.
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.
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.