Django Forms
Django provides a powerful form library that handles form rendering, validation, and processing. Forms in Django simplify the process of collecting user input and validating data.
Creating a Basic Form
Django forms are defined as Python classes. Here's a simple example:
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
Rendering Forms in Templates
You can render forms in templates in several ways:
Manual Rendering
<form method="post">
{% csrf_token %}
<div class="form-group">
{{ form.name.label_tag }}
{{ form.name }}
{{ form.name.errors }}
</div>
<div class="form-group">
{{ form.email.label_tag }}
{{ form.email }}
{{ form.email.errors }}
</div>
<div class="form-group">
{{ form.message.label_tag }}
{{ form.message }}
{{ form.message.errors }}
</div>
<button type="submit">Submit</button>
</form>
Automatic Rendering
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
Other rendering options:
{{ form.as_table }}
- Renders as table rows{{ form.as_ul }}
- Renders as list items
Processing Forms in Views
Here's how to handle form submission in a view:
# 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 the data
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
# Do something with the data (send email, save to DB, etc.)
print(f"Message from {name} ({email}): {message}")
# Redirect to a success page
return redirect('success')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
Form Fields
Django provides many built-in form fields:
CharField
- Text inputIntegerField
- Integer inputDecimalField
- Decimal number inputEmailField
- Email input with validationBooleanField
- CheckboxChoiceField
- Select dropdownDateField
- Date inputFileField
- File uploadImageField
- Image upload
Form Validation
Django forms provide built-in validation:
# Custom validation example
from django import forms
from django.core.exceptions import ValidationError
class ContactForm(forms.Form):
# ... fields ...
def clean_name(self):
name = self.cleaned_data['name']
if len(name) < 3:
raise ValidationError("Name must be at least 3 characters long.")
return name
def clean(self):
cleaned_data = super().clean()
name = cleaned_data.get('name')
email = cleaned_data.get('email')
# Example of cross-field validation
if name and email and name.lower() in email.lower():
raise ValidationError("Name should not be part of the email address.")
ModelForms
ModelForms create forms from Django models:
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2)
# forms.py
from django.forms import ModelForm
from .models import Book
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'published_date', 'price']
File Uploads
Handling file uploads with forms:
# forms.py
from django import forms
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
# views.py
from django.shortcuts import render
from .forms import UploadFileForm
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
# Process the uploaded file
handle_uploaded_file(request.FILES['file'])
return redirect('success')
else:
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})
def handle_uploaded_file(f):
with open(f.name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
Widgets
Customize form field rendering with widgets:
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Your name'
}))
email = forms.EmailField(widget=forms.EmailInput(attrs={
'class': 'form-control',
'placeholder': 'Your email'
}))
message = forms.CharField(widget=forms.Textarea(attrs={
'class': 'form-control',
'rows': 5,
'placeholder': 'Your message'
}))
Form Initial Data
Set initial values for form fields:
# In views.py
form = ContactForm(initial={
'name': 'John Doe',
'email': 'john@example.com'
})
Form Prefixes
Use prefixes when multiple forms are on the same page:
form1 = ContactForm(prefix='contact')
form2 = SubscribeForm(prefix='subscribe')
Form Media (CSS/JS)
Add media files to forms:
from django import forms
class CalendarWidget(forms.TextInput):
class Media:
css = {
'all': ('/css/calendar.css',)
}
js = ('/js/calendar.js',)