Learn How To Use Django Forms
Django is a powerful web framework for building web applications using Python. One of its standout features is its robust form-handling capabilities. Django forms streamline the process of capturing, validating, and processing user input. In this comprehensive article, we'll explore Django forms in depth—starting with basic concepts and working through advanced features, all supported by practical examples.
Table of Contents
- Introduction to Django Forms
- Creating and Rendering a Simple Form
- Handling Form Submissions
- Built-in Field Types and Widgets
- Form Validation
- ModelForms
- Advanced Form Usage
- Customizing Forms with Widgets and CSS
- Handling File Uploads
- Best Practices and Tips
1. Introduction to Django Forms
Django provides several ways to handle forms:
- forms.Form: For manual forms not tied to any model.
- forms.ModelForm: Automatically generates a form from a Django model.
Using Django forms gives you security benefits like CSRF protection and input sanitization.
2. Creating and Rendering a Simple Form
Step 1: Create a Form Class
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(label='Your Name', max_length=100)
email = forms.EmailField(label='Your Email')
message = forms.CharField(widget=forms.Textarea, label='Message')
Step 2: Render the Form in a Template
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Send</button>
</form>
Step 3: Handle Form in Views
from django.shortcuts import render
from .forms import ContactForm
def contact_view(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# process form data
print(form.cleaned_data)
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
3. Handling Form Submissions
When a form is submitted:
- Django binds the form to the data using form = ContactForm(request.POST)
- You call form.is_valid() to validate data.
- Access cleaned data using form.cleaned_data.
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
4. Built-in Field Types and Widgets
Django includes many built-in fields:
- CharField
- EmailField
- IntegerField
- BooleanField
- DateField
- ChoiceField
- FileField
- ImageField
Example
class ExampleForm(forms.Form):
username = forms.CharField(max_length=30)
age = forms.IntegerField()
subscribe = forms.BooleanField(required=False)
birthdate = forms.DateField(widget=forms.SelectDateWidget)
5. Form Validation
Built-in Validation
if form.is_valid():
# cleaned_data is available
Custom Validation
class CustomForm(forms.Form):
code = forms.CharField()
def clean_code(self):
data = self.cleaned_data['code']
if "XYZ" not in data:
raise forms.ValidationError("Code must contain 'XYZ'")
return data
Cross-Field Validation
class RegisterForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get("password") != cleaned_data.get("confirm_password"):
raise forms.ValidationError("Passwords do not match.")
6. ModelForms
ModelForms generate a form based on a model.
Step 1: Define the Model
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
Step 2: Create a ModelForm
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
Step 3: Use in Views
from .forms import PostForm
def post_create(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.save()
else:
form = PostForm()
return render(request, 'post_form.html', {'form': form})
7. Advanced Form Usage
Dynamic Forms
class DynamicForm(forms.Form):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['favorite_color'] = forms.ChoiceField(
choices=[('red', 'Red'), ('blue', 'Blue')]
)
Multiple Forms in One View
if request.method == 'POST':
form1 = Form1(request.POST)
form2 = Form2(request.POST)
if form1.is_valid() and form2.is_valid():
# process both
Formsets
Formsets handle multiple instances of a form.
from django.forms import formset_factory ContactFormSet = formset_factory(ContactForm, extra=2)
8. Customizing Forms with Widgets and CSS
Widgets
class StyledForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Enter your name'
}))
Adding CSS Classes
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
9. Handling File Uploads
Form
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
Template
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
View
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return HttpResponse("File uploaded")
else:
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})
def handle_uploaded_file(f):
with open('uploads/' + f.name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
10. Best Practices and Tips
- Always use CSRF tokens in templates.
- Use form.as_p or customize with {{ form.field }} for full control.
- Always validate using is_valid() before accessing cleaned_data.
- Use ModelForm when working with models to save time.
- Use widgets for better UI integration.
- Sanitize user input with built-in or custom validators.
Conclusion
Django forms are a core part of building robust web applications. Whether you’re collecting contact information, managing user registrations, or uploading files, Django provides an elegant and secure way to handle forms. Understanding the variety of field types, validation methods, and customizations enables you to build scalable and user-friendly forms easily.
With these examples and best practices, you now have the foundation to work with Django forms efficiently and securely. Explore Django documentation for even deeper capabilities like formsets, inline formsets, and class-based views for forms.