Django

Lesson 05

Forms and validation

Use forms or ModelForms to validate request data before creating or updating model instances.

Good Code

reviews/views.py
from django import forms
from django.shortcuts import redirect, render

from .models import Review


class ReviewForm(forms.ModelForm):
    class Meta:
        model = Review
        fields = ["title", "body"]

    def clean_title(self):
        title = self.cleaned_data["title"].strip()
        if "draft" in title.lower():
            raise forms.ValidationError("Use a final review title.")
        return title


def create_review(request):
    form = ReviewForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        review = form.save(commit=False)
        review.author = request.user
        review.save()
        return redirect("reviews:detail", pk=review.pk)

    return render(request, "reviews/form.html", {"form": form})

Bad Code

reviews/views.py
from django.shortcuts import redirect, render

from .models import Review


def create_review(request):
    if request.method == "POST":
        review = Review.objects.create(
            title=request.POST["title"],
            body=request.POST["body"],
            author=request.user,
        )
        return redirect("reviews:detail", pk=review.pk)

    return render(request, "reviews/form.html")

Review Notes

What to review

Good Code

The good version centralizes validation in a form, uses cleaned data through form.save(), and keeps invalid submissions on the form page.

Bad Code

The bad version trusts request.POST directly. Required fields, trimming, error messages, and domain validation are missing from the boundary.

Takeaways

  • Request data should become cleaned data before it changes the database.