First, after some searching online, it seemed several people have experienced similar issues. I happened to run across this answer on stackoverflow for customizing widgets for all forms.
Here's my final code.
def make_custom_datefield(f):
formfield = f.formfield()
if isinstance(f, models.DateField):
formfield.widget.format = '%m/%d/%Y'
formfield.widget.attrs.update({'class':'datePicker', 'readonly':'true'})
return formfield
class ProjectForm(ModelForm):
formfield_callback = make_custom_datefield
class Meta:
model = Project
First, on ProjectForm I specify a custom callback function for handling form fields. This is actually really nice as I can apply this code to any form I want instead of marking individual fields for a form or applying the entire fix to every single model.
In make_custom_datefield I do a quick check to see if it's a model DateField instance. If it is, I do some modifying. First, I change the format of the widget so incoming data from the model match jQuery's format. It might be possible to modify jQuery to match Django, but whatever. Then I add on two custom attributes to the widget. Both of these directly map to html attributes of the input tag.
<input class="datePicker" readonly="true" type="text" id="id_dateDue" />
The datePicker class is important so I can mark this input as a jQuery calendar in the browser. I also mark it as readonly so users can't modify the date with bad formats. Marking the input as read-only is a double-edged sword as it also prevents users from quickly entering dates months or years away.
Once that is working, I just need to add some code to my page that will mark all datePicker instances in javascript as being datepicker widgets.
// on page load
$(function() {
$( ".datePicker" ).datepicker();
});
And that's it! I can now make jQuery UI datepickers the default widget on any django form I choose.
14 comments:
Very helpful for a new Django user thanks!
This worked like a charm and was the clearest explanation I have found online so far. Thanks!
I found bug when U use a widgets property in modelform. I solve this by using send **kwargs to formfield constructor.
Now make_custom_datefield look like that:
def make_custom_datefield(f,**kwargs):
....formfield = f.formfield(**kwargs)
....if isinstance(f, models.DateField):
........formfield.widget.format = '%d/%m/%Y'
........formfield.widget.attrs.update({'class':'datePicker','readonly':'true'})
....return formfield
I think it is simpler to use the widgets meta in your ProjectForm.
Example:
class ProjectForm(ModelForm):
class Meta:
widgets = {
'date': forms.DateInput(format='%Y-%m-%d', attrs={'class':'datePicker', 'readonly':'true'}),
}
Thanks for the detailed conclusion to your(?) slashdot question. I wouldn't have been able to go from the general code on the answer to your final solution easily.
Thanks! Both yours and hleroy's comment helped me a lot. Django forms are kinda confusing if you want to go beyond the basics...
Hi,
your code is very useful to me..
please share the entire code.
I am beginner of django understanding very useful to me.
-Thanks
-Ganesh.
Sleek! Worked right away! Though I customised jQuery UI's datepicker.
So far I have placed the custom function in the models.py file in my app. Any idea what would be a better place to put this function?
Learning Django is not easy, if you want to do amazing things.
I found your post looking for a jquery renderer for django forms.
It is amazing how you gave a solution for a very common issue.
Thank you for sharing it!!
Thank you for this! It came in very handy for me!
2015 and this is exactly what I needed. Thank you! (django 1.8.2, bootstrap 3.3.5)
For any others who happen across this, I've added a wee bit of js using bootstrap so that a nice clickable calendar icon appears in the form field. Looks awesome!
http://pastebin.com/FXADF1Bt
Post a Comment