2010-08-22 131 views
4

我在Django以下模型:如何爲Django Admin創建複雜的Django模型驗證?

class Bout (models.Model): 
    fighter_1 = models.ForeignKey(Fighter, related_name="bout_fighter_1") 
    fighter_2 = models.ForeignKey(Fighter, related_name="bout_fighter_2") 
    winner = models.ForeignKey(Fighter, related_name="bout_winner", 
     blank=True, null=True, help_text='Leave blank for draw.') 
    date = models.DateField() 
    cancelled = models.BooleanField() 

我想「傻瓜型」的管理它的記錄。順便說一句,我想創建三個規則:

  1. 戰鬥機1是不一樣的戰士2(這是唯一的巨蟒小品好)。

  2. 得獎應在回合(即,無論是戰鬥機1或戰鬥機2)

  3. 獲勝者的比賽發生之前不能被設置。 (畢竟,這不是WWE。)

所有這三個規則都需要檢查一個字段與同一記錄中的另一個字段。是否有可能在django中使用本地django方法或使用python?

回答

1

簡短的回答:你可以在Django中使用「native django methods」來實現這一點。我不確定你的意思是什麼「本地Django方法」;我假設你的意思是調用Django API。

有幾種方法可以解決這個問題。如果您的用戶只能使用您提供的表單創建Bout實例,則表單的驗證方法可以測試您提到的條件。例如:

class BoutForm(forms.ModelForm): 
    class Meta: 
     model = Bout 

    def clean(self): 
     fighter_1 = self.cleaned_data.get('fighter_1') 
     fighter_2 = self.cleaned_data.get('fighter_2') 
     winner = self.cleaned_data.get('winner') 
     date = self.cleaned_data.get('date') 

     if not (fighter_1 and fighter_2 and (fighter_1.id != fighter_2)): 
      raise forms.ValidationError("Both fighters cannot be the same") 

     if not (winner and (winner.id == fighter_1.id or winner.id == fighter_2.id)): 
      raise forms.ValidationError("Winner is not in the fight") 

     if not (date and date < datetime.today()): 
      raise forms.ValidationError("Winner is not in the fight") 

     return self.cleaned_data 

上面的代碼片段不完整。你可以調整它來滿足你的需求。另外看看Django的新混跡form validators

如果在另一方面你的用戶可以創建使用API​​(比如,通過實例在其方案中Bout類)的情況下,那麼你就必須通過覆蓋Bout類的save()方法來做驗證。

+0

乾杯的響應。目前我只關心管理員的輸入。 關於你的回答,這與我在與一位朋友交談時提出的答案非常相似,儘管時間稍長。特別是,在您的方法中,您首先獲取數據並將其複製到局部變量,然後返回cleared_data。 是否有任何理由選擇不直接測試self.fighter_1,self.fighter_2,self.winer和self.date? – 2010-08-22 18:17:42

+0

我正在關注從'cleaned_data'屬性中拾取數據而不是直接使用'self.field_name'的Django習慣用法。文檔建議這是出於很好的理由:http://docs.djangoproject.com/en/dev/topics/forms/#processing-the-data-from-a-form – 2010-08-23 05:33:03

+0

乾杯的解釋性鏈接。 :-) – 2010-08-23 10:29:00

0

雖然馬諾Govindan的答案看起來非常好,我也想出了自己的解決方案......我會在這裏包括它的情況下,任何人發現我最好稍短的解決方案:

def clean(self): 
    if self.fighter_1 == self.fighter_2: 
     raise ValidationError('Fighter 1 can not be Fighter 2.') 
    if (self.winner != self.fighter_1) and (self.winner != self.fighter_2): 
     raise ValidationError('Winner must be in the bout.') 
    if (self.date >= datetime.date.today()) and (self.winner): 
     raise ValidationError('Winner can not be set before match.') 
+0

我需要糾正自己。第二次和第三次驗證測試都應該開始: if(self.winner)and ...這樣如果沒有選擇贏家,這些測試的其餘部分不會執行。 (是的,我包括(self.winner)已經在第三次測試中,但是當我把它放在那裏時它不能正常工作。當它在那裏時,它實質上將贏家場變成必需場。 – 2010-08-23 04:57:08