2016-10-01 53 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']