Forms and User Input

Handling user input is a common requirement in web applications. Django provides a robust and flexible framework for working with forms, including tools for form handling, validation, and integration with models.

Django Form Handling

Django forms are Python classes that represent HTML forms. They provide an easy way to handle user input, validate data, and render forms in templates.

Creating a Form

To create a form, define a class that inherits from django.forms.Form. Each form field is defined as a class attribute.

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

Rendering a Form in a Template

To render a form in a template, pass an instance of the form to the template context and use the form object in the template.

Python file:

from django.shortcuts import render
from .forms import ContactForm

def contact(request):
    form = ContactForm()
    return render(request, 'contact.html', {'form': form})

HTML file:

<!-- contact.html -->
<form method="post" action="/contact/">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Send</button>
</form>

In this example, form.as_p renders the form fields wrapped in <p> tags.

Processing Form Data

When a user submits the form, we need to process the data in our view.

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ContactForm

def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            # Process the data in form.cleaned_data
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            message = form.cleaned_data['message']
            # Redirect after processing
            return HttpResponseRedirect('/thanks/')
    else:
        form = ContactForm()

    return render(request, 'contact.html', {'form': form})

Form Validation

Django forms provide built-in validation methods to ensure that the data submitted by the user is valid.

Built-in Validators

Each form field type comes with its own built-in validators. For example, CharField validates that the input is a string, and EmailField validates that the input is a valid email address.

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

Custom Validators

You can add custom validation logic by defining a clean_<fieldname> method in your form class.

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

    def clean_name(self):
        name = self.cleaned_data.get('name')
        if "badword" in name:
            raise forms.ValidationError("Bad word detected!")
        return name

Global Form Validation

To add validation that spans multiple fields, override the clean method of the form class.

class ContactForm(forms.Form):
    name = forms.CharField(max_length=100)
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

    def clean(self):
        cleaned_data = super().clean()
        name = cleaned_data.get('name')
        email = cleaned_data.get('email')

        if name and email:
            if "example" in email:
                raise forms.ValidationError("Example email addresses are not allowed.")

Model Forms

Model forms are a shortcut for creating forms based on Django models. They provide a way to create forms directly from your models.

Creating a Model Form

To create a model form, define a class that inherits from django.forms.ModelForm and specify the model and fields.

Model:

from django.db import models

class Contact(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    message = models.TextField()

Model Form:

from django import forms
from .models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        fields = ['name', 'email', 'message']

Using a Model Form in a View

Using a model form in a view is similar to using a regular form.

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ContactForm

def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            form.save()  # Saves the form data to the database
            return HttpResponseRedirect('/thanks/')
    else:
        form = ContactForm()

    return render(request, 'contact.html', {'form': form})