Forms are one of the best features of Django. (After models, admin, url routing etc
). Here is a quick tutorial describing how to do things with Django forms.
- Basic form
Prob. You want to show a form, validate it and display it.
Ans. Create a simple form.
class UserForm(forms.Form):
username = forms.CharField()
joined_on = forms.DateField()
This wil take care that the form is displayed with two text field, and a value for them are filled in, and the second field has correct formatting for a date.
2.
Prob. Create a form which has values populated depending upon a runtime value, eg you might want to show only the values corresponding to the current subdomain.
Ans. Create a form with an custom __init__.
class UserForm(forms.Form):
username = forms.CharField()
plan = forms.ModelChoiceField(queryset = Plan.objects.none())
def __init__(self, subdomain, *args, **kwargs):
self.default_username = default_username
super(UserForm, self).__init__(*args, **kwargs)
self.fields['plan'].queryset = Plan.objects.filter(subdomain = subdomain)
Here in the __init__ we are overriding the default queryset on field plan. Any of the attributes can similarly be overridden.
However the self.fields is populated only after super(UserForm, self).__init__(*args, **kwargs) is called.
3.
Prob. The same form is used in multiple views, and handles the cleaned_data similarly.
Ans. Create a form with a custom .save()
class UserForm(forms.Form):
username = forms.CharField()
def save(self):
data = self.cleaned_data
user = User.objects.create(username = data['username'])
#create a profile
UserProfile.objects.create(user = user, ...some more data...)
You could have called this method anything, but this is generally called save, to maintain similarity with ModelForm
4.
Prob. You need to create a form with fields which have custom validations.
Ans. Create a form with custom clean_fieldname
class UserForm(forms.Form):
username = forms.CharField()
def clean_username(self):
data = self.cleaned_data
try:
User.objects.get(username = data['username'])
except User.DoesNotExist:
return data['username']
raise forms.ValidationError('This username is already taken.')
Here we can validate that the usernames are not repeated.
5.
Prob. You want to create a field which has cross field validations.
Ans. Create a field with a .clean
class UserForm(forms.Form):
username = forms.CharField()
password1 = forms.PasswordField()
password2 = forms.PasswordField()
def clean(self):
data = self.cleaned_data
if "password1" in data and "password2" in data and data["password1"] != data["password2"]:
raise forms.ValudationError("Passwords must be same")
6.
Problem.
You need a form the fields of which depends on some value in the database. Eg. The field to be shown are customisable per user.
Create a form dynamically
def get_user_form_for_user(user):
class UserForm(forms.Form):
username = forms.CharField()
fields = user.get_profile().all_field()
#Use field to find what to show.
This post provides much more details
7.
Prob. You need to create a Html form which writes to multiple Django models.
Ans. Django forms are not a one to one mapping to Html forms.
#in forms.py
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ["username", "email"]
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
#in views.py
def add_user(request):
...
if request.method == "POST":
uform = UserForm(data = request.POST)
pform = UserProfileForm(data = request.POST)
if uform.is_valid() and pform.is_valid():
user = uform.save()
profile = pform.save(commit = False)
profile.user = user
profile.save()
....
...
#in template
<form method="post">
{{ uform.as_p }}
{{ pform.as_p }}
<input type="submit" ...>
</form>
8.
Prob. You want to use multiple forms of same type on one page.
Ans.
a. If you want a datagrid style ui, use formset.
from django.forms.formsets import formset_factory
forms = formset_factory(UserForm, extra = 4)
#
Formsets are described much more comprehensively here
b. If you do not need a datagrid style ui, use prefix argument to forms.
Eg. you have a survey app, and you want a page with all questions from that survey displayed.
#IN views.py
def survey(request, survey_slug)
...
questions = survey.questions.all()
question_forms = []
for question in questions:
qform = QuestionForm(question=question, prefix = question.slug)
question_forms.append(qform)
...
if request.method == "POST":
for question in questions:
qform = QuestionForm(question=question, prefix = question.slug, data = request.POST)
#Validate and do save action
...
...
Do you subscribe to our feed? We recently made a full text feed available, so if you are using the old feed, you should change it. Subscribe now.
Related posts:

{ 1 trackback }
{ 40 comments… read them below or add one }
Nice round up of use cases and solutions. This is a good reference for noobs and experienced Django devs. Thanks.
Cool post. Thanks. Suggestion for future post: How to use static values in a formset. For example display a list view of items, but with an enable/disable check box on each item. I tried using a formset containing a BooleanField, but could not figure out how to add static fields to it. And for extra credit, update check box value via AJAX.
Thanks for this post. Very helpful!
Dave:
I dont think you can use formset for that, you should use the second method, and set prefixes manually, eg
for question in survey.questions.all(): qform = SurveyForm(survey, prefix = question.slug) if questions.is_optional: qform.set_optional()
Etc
I like Django! Thanks for info about this
Hey, at the code snippet at number 4, shouldn’t it be “except User.DoesNotExist” instead of “User.DoesNotExist:” ?
@geo: Thanks, updated the posts.
Foe no. 6, the definition of the class UserForm changes depending on which employee is involved. if I just create an new instance of UserForm, how does Python know which definition to use?
Hi, i tried that example and i didn’t get one part working from the beginning, how come it doesn’t work for me?
New blog post. Doing things with Django forms. http://bit.ly/7YRyoJ
This comment was originally posted on Twitter
Doing things with Django forms: Forms are one of the best features of Django. (After models, admin, url routing.. http://bit.ly/6lNinJ
This comment was originally posted on Twitter
Shabda Raaj: Doing things with Django forms http://bit.ly/5l5BRq
This comment was originally posted on Twitter
Good link; thanks. There are a lot of things in here that took me quite a while to dope out.
This comment was originally posted on Reddit
Doing things with Django forms: http://bit.ly/4VdFYV Comments: http://bit.ly/7nRyXQ
This comment was originally posted on Twitter
HNews: Doing things with Django forms http://bit.ly/8wedHP
This comment was originally posted on Twitter
via del.icio.us: The real guide to django forms http://bit.ly/6EdrkW
This comment was originally posted on Twitter
Django Forms: http://bit.ly/7Kyun6
This comment was originally posted on Twitter
Agreed, forwarded this to a couple of my friends who have just started developing for Django.. very nice examples
This comment was originally posted on Reddit
StartupNews: Doing things with Django forms http://bit.ly/74I3Vt
This comment was originally posted on Twitter
Doing things with Django forms http://bit.ly/8wedHP
This comment was originally posted on Twitter
Nice summary.
This comment was originally posted on Hacker News
Forms are the biggest difference between Rails itself and Rails-inspired Python frameworks (I’m talking about Pylons’s default helpers, Toscawidgets and Django here)After working with Rails for 3 years I am absolutely don’t get the need for "form" classes. And indeed, judging by open sourced projects and posted code examples, submit handlers in Django and Pylons always look insanely complex as compared to Rails.
This comment was originally posted on Hacker News
Doing things with Django forms http://ff.im/-ejP4O
This comment was originally posted on Twitter
Django isn’t Rails-inspired – they were developed at around the same time, with no real awareness of each other (at first).As to the merits of "form" classes and post handlers, I think the complexity is only there if you need it, if you’re doing something more interesting (read: complex) than CRUD-type inserts/updates and basic validation (if that’s all you’re doing, ModelForms are pretty close to magical and light on syntax).
This comment was originally posted on Hacker News
Shameless self-promotion: * [Intro to the forms library, part 1](http://www.b-list.org/weblog/2007/nov/22/newforms/) (from not long after it was added, back when it was `django.newforms` instead of just `django.forms`) * [Part 2](http://www.b-list.org/weblog/2007/nov/23/newforms/) * [Dynamic forms](http://www.b-list.org/weblog/2008/nov/09/dynamic-forms/)
This comment was originally posted on Reddit
I have those bookmarked; they were a big help also. Thank you for those.
This comment was originally posted on Reddit
These tips would have been nice as a django noob. I think they really belong in the docs. http://bit.ly/7bfNsH !a #django !import (maybe?)
This comment was originally posted on Twitter
Dude, where was this 1 month ago when I really needed it?! Shit, bookmarked!
This comment was originally posted on Reddit
I’ve got a question for you. I’ve got a dynamic form set up with a foreign key pointing to another model. I’ve been unable to find an easy way of including an add button into the form so that the user can add an entry to the other model and have it immediately reflected on the form that they were editing before. The way i’m envisioning it, it would work similar to the way that kind of thing is handled in the admin section. Could you perhaps point me in the right direction?
This comment was originally posted on Reddit
Doing things with Django forms
: http://bit.ly/8UIrOz
This comment was originally posted on Twitter
Doing things with Django forms http://bit.ly/8QKWmx
This comment was originally posted on Twitter
Doing things with Django forms: Comments http://url4.eu/18MPU
This comment was originally posted on Twitter
Django forms (and their non-Django counterpart, WTForms) are very easy to use, with a declarative syntax.The advantage is that validation is decoupled from models. Often you need to handle validation which doesn’t directly involve a single model – for example sending an email, or handling updates to a number of models. This saves you having to litter your controller/views with validation code.
This comment was originally posted on Hacker News
Perhaps, a side block next to articles, linking to other articles in the same tag, and some random articles might be helpful?
This comment was originally posted on Reddit
http://icio.us/xwuxlg
This comment was originally posted on Twitter
Doing things with Django forms: http://bit.ly/6ZStT4
This comment was originally posted on Twitter
Doing things with Django forms — The Usware Blog – Django Web Development: Tags: django Posted by: jsuntheimer http://bit.ly/6ze24s
This comment was originally posted on Twitter
Doing things with Django forms — The Usware Blog – Django Web Development http://ff.im/-eq838
This comment was originally posted on Twitter
Doing things with Django forms — The Usware Blog – Django Web Development http://bit.ly/8TPjdM forms django tutorial
This comment was originally posted on Twitter
#django: http://uswaretech.com/blog/2010/01/doing-things-with-django-forms/
This comment was originally posted on Twitter