【问题标题】:Django ModelForm Validation using non form data使用非表单数据的 Django ModelForm 验证
【发布时间】:2016-07-25 02:21:59
【问题描述】:

我是 Django (1.9.6) 的新手,我正在尝试了解是否可以验证 ModelForm 上需要引用包含在引用模型的外键中的信息的字段。

如何验证用户在 OrderForm 上为“num_tickets”输入的值小于或等于“tickets_remaining” " 通过外键关系连接的 Event 类上的字段?

我不想在 OrderForm 上的 Order 类中公开 Event 字段,因为用户已经访问了特定事件页面,并已选择购票。

模型.py

class Order(models.Model):

    first_name = models.CharField('First Name', max_length=120,null=False, blank=False)
    last_name = models.CharField('Last Name', max_length=120, null=False, blank=False)
    email = models.EmailField('Email', null=False, blank=False)
    event = models.ForeignKey(Event)
    num_tickets = models.PositiveIntegerField('Tickets', null=False, blank=False, validators=[MinValueValidator(0)])
    total_price = models.DecimalField('Total', max_digits=8, decimal_places=2, default=0.0)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)

class Event(models.Model):

    event_name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits=8, decimal_places=2, default=00.00, validators=[MinValueValidator(0)])
    tickets_remaining = models.PositiveIntegerField(default=300)

Forms.py

class OrderForm(forms.ModelForm):

class Meta:
    model = Order
    fields = ['first_name', 'last_name', 'email', 'num_tickets']

def clean_num_tickets(self):
    tickets = self.cleaned_data["num_tickets"]

    # validation Logic. Want to ensure a user cannot purchase more
    # tickets than what an event has for "tickets_remaining"

    return tickets

【问题讨论】:

    标签: django django-forms django-validation


    【解决方案1】:

    首先,您没有展示如何将订单与事件相关联。如果您还没有这样做,那么您的问题不仅仅是验证可用的票证。

    我建议将该事件从视图传递到表单实例化中。然后,您可以使用它来将订单与该事件相关联,并验证票证。

    class OrderForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            self.event = kwargs.pop('event', None)
            super(OrderForm, self).__init__(*args, **kwargs)
    
        def clean_num_tickets(self):
            tickets = self.cleaned_data["num_tickets"]
            if tickets > self.event.tickets_remaining:
                raise ValidationError('Too many tickets')
            return tickets
    
        def save(self, commit=False):
            order = super(OrderForm, self).save(commit=False)
            order.event = self.event
            if commit:
                order.save()
            return commit
    

    现在在实例化时将事件传递到表单中:

    form = OrderForm(request.POST, event=event)
    

    【讨论】:

    • 非常感谢您的帮助。我浏览了 Django 教程,但没有明确提到重载 ModelForm 的构造函数。这肯定有助于更好地理解框架。
    猜你喜欢
    • 2017-10-06
    • 2011-01-13
    • 2012-09-30
    • 2011-01-09
    • 2013-04-05
    • 2012-11-03
    • 1970-01-01
    • 2013-11-26
    相关资源
    最近更新 更多