Django forms are powerful modules to help Django application development in rendering HTML from the model and validating input from httprequest to model specifications. And we can extend the module to suit our exact needs. Let's see the basics of Django forms.
Forms:
A collection of fields that knows how to validate itself, Form classes are created as subclasses of django.forms.Form
Example:
Consider a form used to implement add menu item functionality
create models.py
from django.db import models
class Menu(models.Model):
title = models.CharField(max_length=100)
content = models.CharField(max_length=100)
order = models.IntegerField()
create forms.py
from django import forms
class MenuForm(forms.Form):
title = forms.CharField(max_length=100)
content = forms.CharField(max_length=100)
order = models.IntegerField()
A form is composed of Field objects.
Using a form in a view:
django.http import HttpResponse
from app.forms import MenuForm
def add_menu(request):
if request.method == "POST":
form = MenuForm(request.POST)
if form.is_valid():
title = request.POST.get("title")
content = request.POST.get("content")
order = Menu.objects.all().count() + 1
menu = Menu.objects.create(title=title,content=content, order=order)
return HttpResponse("Menu Successfully created")
else:
return HttpResponse("form is not validated")
ModelForm:
ModelForm is used to avoid duplicating Model description, to do field validations. We can also use it override model save method.
create forms.py:
from django.forms import ModelForm
from app.models import Menu
class MenuForm(ModelForm):
class Meta:
model = Menu
exclude = ('order')
def clean_title(self):
title = self.cleaned_data['title']
if self.instance.id:
if Menu.objects.filter(title=title).exclude(id=self.instance.id):
raise forms.ValidationError(
'Menu with this title already exists.')
else:
if Menu.objects.filter(title=title):
raise forms.ValidationError(
'Menu with this subject already exists.')
return title
def clean_content(self):
content = self.cleaned_data['content']
if len(content) > 80:
raise forms.ValidationError(
'content should not exceed 80 characters')
return subject
def save(self, commit=True):
instance = super(MenuForm, self).save(commit=False)
all_menus = Menu.objects.filter(project=self.project)
if not self.instance.order:
instance.order = all_menus.count() + 1
if commit:
instance.save()
return instance
Using a form in a view:
from django.http import HttpResponse
from app.forms import MenuForm
def add_menu(request):
if request.method == "POST":
form = MenuForm(request.POST)
if form.is_valid():
menu = form.save()
return HttpResponse("Contact details created")
else:
return HttpResponse("form is not validated")
If we’re using the same HTML for each of your form fields, by passing form object to html we can reduce duplicate code by looping through each field in turn using a {% for %} loop:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
def add_menu(request):
form = MenuForm()
return render('add_menu.html', {'form': form})