2016-07-25 32 views
0

我是Django(1.9.6)的新手,我想了解是否可以驗證ModelForm中需要引用包含在外部信息中的字段引用模型的關鍵。使用非表單數據的Django ModelForm驗證

如何可以驗證該值的用戶用於在OrderFormnum_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

你不告訴你是如何與關聯擺在首位的事件順序。如果你還沒有這樣做,那麼你的問題比驗證可用的門票更廣泛。

我建議將該事件從視圖傳遞到表單實例。然後,您可以使用它將訂單與該事件相關聯,並驗證票證。

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) 
+0

我非常感謝幫助。我經歷了Django教程,但是沒有明確提及重載ModelForm的構造函數。這將有助於更好地理解框架。 – JR90