Menu
CoddyTech

完整活动

本课属于 Coddy Django 学习旅程的“表单”单元。第 17 课,共 20 课。

陶艺课有 2 个位置和 2 位客人,但它的表单仍然接受更多报名。规则应该放在表单中,但只有视图知道这个表单对应哪个活动。

表单是一个 Python 类,所以你可以为它编写自己的 __init__。将额外的值作为关键字参数接收,将它保存在 self 上,然后把其余参数传给 super().__init__()。需要拍卖物品的竞价表单如下:

class BidForm(forms.Form):
    amount = forms.IntegerField()

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

    def clean_amount(self):
        amount = self.cleaned_data["amount"]
        if amount <= self.item.top_bid:
            raise forms.ValidationError("Bid more than the top bid.")
        return amount

视图每次创建表单时都会传入物品:BidForm(request.POST, item=item)。在签名中命名 item,可以让它不进入 **kwargs;Django 的表单不认识它,并会引发 TypeError。

challenge icon

挑战

中等

满员活动不接受报名。

  1. 在 events/forms.py 中,为 RSVPForm 添加 __init__,让它将关键字参数 event 保存到 self.event,并将其余参数传给 super().__init__。
  2. 在它的 clean() 中,当宾客人数达到 capacity 时,抛出 Sorry, this event is full.。还剩 1 个名额时,仍然可以接受报名。
  3. 在 event_detail 中,向两处 RSVPForm 调用都传入 event。

报名参加陶艺课:你会看到 Sorry, this event is full.

亲手试试

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"]
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

表单中的所有课

自己练习: Django 在线编辑器