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:
        self.add_error("phone", "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.

self.add_error() puts a message under one field. Raising forms.ValidationError in clean() makes an error of the whole form, which no field draws: {{ form.non_field_errors }} does.

challenge icon

Challenge

Medium
  • Add end_date to EventForm after date: a date that may be empty.
  • Refuse an end before the start with The event cannot end before it starts., an error of the whole form.
  • Save end_date in new_event.
  • Show the whole form's errors above the fields.

Press Run and try an end before the start.

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