Menu
CoddyTech

One RSVP per Email

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

This chapter is yours: three features for the events board, built with what you know. Each task says what the site must do; the code is up to you.

Right now Ada can RSVP to Friday Jazz Night as often as she likes, and every RSVP takes a place. One email should hold one place per event.

You have every piece: a clean_<field> method, the event the form keeps in self.event, and its RSVPs in self.event.rsvps. One more lookup helps: email__iexact compares text without case, because Ada@Example.com and ada@example.com reach the same inbox.

challenge icon

Challenge

Medium

Refuse a second RSVP from the same email to the same event, with This email is already on the guest list. under the email field.

  • Capitals do not matter: ADA@Example.com is ada@example.com.
  • The same email can still RSVP to another event.

Press Run and RSVP twice to Friday Jazz Night with one email.

Try it yourself

import datetime

from django import forms

from .models import RSVP, Event


class EventForm(forms.ModelForm):
    class Meta:
        model = Event
        fields = ["title", "date", "end_date", "place", "description", "capacity"]

    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

    def clean(self):
        cleaned_data = super().clean()
        date = cleaned_data.get("date")
        end_date = cleaned_data.get("end_date")
        if date and end_date and end_date < date:
            raise forms.ValidationError("The event cannot end before it starts.")
        return cleaned_data


class RSVPForm(forms.ModelForm):
    class Meta:
        model = RSVP
        fields = ["name", "email"]

    def __init__(self, *args, event=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.event = event

    def clean(self):
        cleaned_data = super().clean()
        if self.event.rsvps.count() >= self.event.capacity:
            raise forms.ValidationError("Sorry, this event is full.")
        return cleaned_data

All lessons in Forms

Practice on your own: Django playground