Django Forms - Forms, Widgets, Validation

DjangoDjango FormsFree Lesson

Advertisement

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

  1. Create a registration form with username, email, password, and confirm password fields
  2. Implement a form that allows uploading multiple files with validation
  3. Build a form with dependent fields (selecting country updates states dropdown)
  4. Create a custom widget that displays a rich text editor
  5. Implement form validation that checks for password complexity requirements

Advertisement

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement