使用非表单数据的Django ModelForm验证

时间:2016-07-25 02:21:59

标签: django django-forms django-validation

我是Django的新手(1.9.6),我试图了解是否有可能验证ModelForm上的一个字段,该字段需要引用来自引用模型的外键中包含的信息。 / p>

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

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

Models.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

1 个答案:

答案 0 :(得分: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)