RelatedObjectDoesNotExist - 在模型的清理功能中

时间:2016-10-01 21:55:58

标签: django

我有模特

@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']  

并且每次保存此表单而不选择我正在获取的单位的值

  

错误RelatedObjectDoesNotExist

来自模型中的clean函数,因为没有self.unit

但是我明确地验证了单位字段。(至少我相信)

我做错了什么?

1 个答案:

答案 0 :(得分:1)

  

请注意,调用时不会自动调用full_clean()   你的模型的save()方法。你需要手动调用它   想要为您自己手动创建的一步模型验证运行   楷模。 [docs]

这显然是出于向后兼容性原因,请检查this票证。

模型的full_clean()方法负责调用Model.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']