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_dataA 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
Medium- Add
end_datetoEventFormafterdate: 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_dateinnew_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
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Forms
2Django Forms
A Django FormDrawing a FormPractice on your own: Django playground