Menu
CoddyTech

Checking Two Fields

Part of the Forms section of Coddy's Django journey. Lesson 11 of 20.

The Winter Book Fair lasts three days, and an end must not come before its start. A clean_<field> method sees one field, so a rule across fields goes in clean(), which runs after every field's own checks. A booking form where a group over 6 must leave a phone number:

def clean(self):
    cleaned_data = super().clean()
    guests = cleaned_data.get("guests")
    phone = cleaned_data.get("phone")
    if guests and guests > 6 and not phone:
        raise forms.ValidationError("Groups over 6 need a phone number.")
    return cleaned_data

A field that failed is missing from cleaned_data, and an empty optional date is None, so read with .get() and compare only when both values are there.

An error raised in clean() belongs to the whole form, so the field loop does not draw it. {{ form.non_field_errors }} does.

challenge icon

Challenge

Medium

Events get an end date.

  1. In events/forms.py, add an optional end_date date field to EventForm. Write clean(): when both dates are there and the end comes first, raise The event cannot end before it starts. Read the dates with .get().
  2. In new_event, save end_date too.
  3. In new_event.html, draw form.non_field_errors above the loop.

Set the end before the start: you see that message.

Try it yourself

import datetime

from django import forms


class EventForm(forms.Form):
    title = forms.CharField(max_length=100)
    date = forms.DateField()
    place = forms.CharField(max_length=100)
    description = forms.CharField(widget=forms.Textarea, required=False)
    capacity = forms.IntegerField(min_value=1)

    def clean_date(self):
        date = self.cleaned_data["date"]
        if date < datetime.date.today():
            raise forms.ValidationError("The date cannot be in the past.")
        return date
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Forms

Practice on your own: Django playground