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.
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
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.
self.fields is populated only after
super(UserForm, self).__init__(*args, **kwargs) is called.
Prob. The same form is used in multiple views, and handles the
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
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.
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")
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
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"> <input type="submit" ...> </form>
Prob. You want to use multiple forms of same type on one page.
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](http://docs.djangoproject.com/en/dev/topics/forms/formsets/)
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.
Thank you for reading the Agiliq blog. This article was written by shabda on Jan 14, 2010 in tutorial .
You can subscribe ⚛ to our blog.
We love building amazing apps for web and mobile for our clients. If you are looking for development help, contact us today ✉.
Would you like to download 10+ free Django and Python books? Get them here