2016-10-01 52 views
0

我有模型RelatedObjectDoesNotExist - 在模型的清潔功能

@with_author 
class Lease(CommonInfo): 
    version = IntegerVersionField() 
    is_renewed = models.BooleanField(default=False) 
    unit = models.ForeignKey(Unit) 
    is_terminated = models.BooleanField(default=False) 
    def __unicode__(self): 
     return u'%s %i %s ' % ("lease#", self.id, self.unit) 

    def clean(self): 
     model = self.__class__ 
     if self.unit and (self.is_active == True) and model.objects.filter(unit=self.unit, is_terminated = False , is_active = True).count() == 1: 
      raise ValidationError('Unit has active lease already, Terminate existing one prior to creation of new one or create a not active lease '.format(self.unit)) 

和我有一個表格

class LeaseForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(LeaseForm, self).__init__(*args, **kwargs) 
     self.fields['unit'].required = True 

    class Meta: 
     model = Lease 
     fields = [ 'unit', 
     'is_active','is_renewed', 'description'] 

,每次保存這種形式不爲單位我收到

選擇價值

error相關對象DoesNotExist

從模型我清潔功能,因爲沒有self.unit

但我明確地驗證單元領域。(至少我這樣認爲)

我究竟做錯了什麼?

回答

1

請注意,當您調用 模型的save()方法時,不會自動調用full_clean()。當您想要爲您自己手動創建的 模型運行一步模型驗證時,您需要手動調用它。 [docs]

這顯然是向後兼容的原因做了,檢查this票了。

模型的full_clean()方法負責調用Model.clean(),但由於它從未被調用過,所以模型內部的clean方法基本上被省略了。

你可以爲此做幾件事情。您可以手動調用模型的清潔。或者,您可以使用其清潔方法將驗證邏輯移至ModelForm。如果您主要通過表單創建實例,我認爲這是執行驗證的最佳位置(以及更常見的做法)。

試試這個:

class LeaseForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(LeaseForm, self).__init__(*args, **kwargs) 
     self.fields['unit'].required = True 


    # IF your validation logic includes multiple fields override this 
    def clean(self): 
     cleaned_data = super(LeaseForm, self).clean() 
     # .. your logic 
     return cleaned_data 

    # IF just your field's value is enough for validation override this 
    def clean__unit(self): 
     data = self.cleaned_data.get('unit', None) 
     # .. your logic 
     return data 

    class Meta: 
     model = Lease 
     fields = [ 'unit', 
     'is_active','is_renewed', 'description']