Introduction
Django forms handle form rendering, validation, and processing. Forms provide a clean way to collect and validate user input while protecting against common security issues.
Basic Form Definition
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=100, required=True)
email = forms.EmailField(required=True)
message = forms.CharField(widget=forms.Textarea, required=True)
subscribe = forms.BooleanField(required=False, initial=True)
def clean_name(self):
name = self.cleaned_data['name']
if len(name) < 2:
raise forms.ValidationError('Name must be at least 2 characters')
return name
def clean(self):
cleaned_data = super().clean()
email = cleaned_data.get('email')
name = cleaned_data.get('name')
if email and name:
if name.lower() in email.lower():
raise forms.ValidationError('Name should not appear in email')
return cleaned_data
# ModelForm
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
status = models.CharField(max_length=20, default='draft')
published_date = models.DateField(null=True, blank=True)
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'content', 'status']
widgets = {
'content': forms.Textarea(attrs={'rows': 10, 'class': 'editor'}),
'title': forms.TextInput(attrs={'class': 'form-control'}),
}
Custom Widgets
class CustomForm(forms.Form):
date = forms.DateField(
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'})
)
color = forms.ChoiceField(
choices=[('red', 'Red'), ('blue', 'Blue'), ('green', 'Green')],
widget=forms.RadioSelect
)
bio = forms.CharField(
widget=forms.Textarea(attrs={'rows': 4, 'maxlength': 500})
)
# Custom widget
class CustomTextInput(forms.TextInput):
def __init__(self, *args, **kwargs):
self.icon = kwargs.pop('icon', None)
super().__init__(*args, **kwargs)
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
if self.icon:
context['widget']['icon'] = self.icon
return context
Form Processing in Views
# views.py
from django.shortcuts import render, redirect
from .forms import ContactForm
def contact_view(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# Process form data
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
# Save or send data
send_email(name, email, message)
return redirect('success')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
# ModelForm in view
from django.views.generic import CreateView
from .models import Article
from .forms import ArticleForm
class ArticleCreateView(CreateView):
model = Article
form_class = ArticleForm
template_name = 'article_form.html'
success_url = '/articles/'
Practice Problems
- Create a registration form with username, email, password, and confirm password fields
- Implement a form that allows uploading multiple files with validation
- Build a form with dependent fields (selecting country updates states dropdown)
- Create a custom widget that displays a rich text editor
- Implement form validation that checks for password complexity requirements