CodeToLive

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 input
  • IntegerField - Integer input
  • DecimalField - Decimal number input
  • EmailField - Email input with validation
  • BooleanField - Checkbox
  • ChoiceField - Select dropdown
  • DateField - Date input
  • FileField - File upload
  • ImageField - 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',)