Mini-Build: Contact & Registration Forms
Build a complete contact form with email validation and a user registration form with password confirmation. This mini-build applies all form concepts — validation, error handling, messages, and CSRF protection.
25 min•By Priygop Team•Updated 2026
Project Features
- Contact form: name, email, subject, message
- Registration form: username, email, password, confirm password
- Custom validation for each form
- Error display with user-friendly messages
- Flash messages for success/failure
- CSRF protection on all forms
- Clean form rendering with custom styling
Contact & Registration Forms
Contact & Registration Forms
# accounts/forms.py
# from django import forms
# from django.contrib.auth.models import User
# from django.core.exceptions import ValidationError
# class ContactForm(forms.Form):
# name = forms.CharField(max_length=100)
# email = forms.EmailField()
# subject = forms.CharField(max_length=200)
# message = forms.CharField(widget=forms.Textarea(attrs={'rows': 5}))
#
# def clean_email(self):
# email = self.cleaned_data['email']
# if email.endswith('.xyz'):
# raise ValidationError('Please use a valid email address.')
# return email
# class RegistrationForm(forms.Form):
# username = forms.CharField(min_length=3, max_length=30)
# email = forms.EmailField()
# password = forms.CharField(
# min_length=8,
# widget=forms.PasswordInput
# )
# confirm_password = forms.CharField(
# widget=forms.PasswordInput
# )
#
# def clean_username(self):
# username = self.cleaned_data['username']
# if User.objects.filter(username=username).exists():
# raise ValidationError('Username already taken.')
# return username
#
# def clean(self):
# cleaned = super().clean()
# pw = cleaned.get('password')
# cpw = cleaned.get('confirm_password')
# if pw and cpw and pw != cpw:
# raise ValidationError('Passwords do not match.')
# return cleaned
# accounts/views.py
# from django.contrib import messages
# from django.contrib.auth.models import User
#
# def register(request):
# if request.method == 'POST':
# form = RegistrationForm(request.POST)
# if form.is_valid():
# User.objects.create_user(
# username=form.cleaned_data['username'],
# email=form.cleaned_data['email'],
# password=form.cleaned_data['password'],
# )
# messages.success(request, 'Account created!')
# return redirect('login')
# messages.error(request, 'Please fix the errors below.')
# else:
# form = RegistrationForm()
# return render(request, 'accounts/register.html', {'form': form})Tip
Tip
Use TemplateView for simple static pages. It's cleaner than writing a function view just to render a template.
Diagram
Loading diagram…
QuerySets are LAZY — no DB hit until evaluated.
Common Mistake
Warning
Overcomplicating simple views with CBVs. TemplateView for static pages, FBVs for unique logic.
Practice Task
Note
(1) Build a complete CRUD system with CBVs. (2) Add search, pagination, and auth. (3) Compare with equivalent FBVs.
Quick Quiz
Key Takeaways
- Build a complete contact form with email validation and a user registration form with password confirmation.
- Contact form: name, email, subject, message
- Registration form: username, email, password, confirm password
- Custom validation for each form