表单验证期间的RelatedObjectDoesNotExist

时间:2016-11-02 12:29:36

标签: django

我有一个让我疯狂的问题

我有模特

class Property1(CommonInfo):
    unit = models.ForeignKey(Unit)
    is_true = models.BooleanField(default=False)
    propertytype = models.ForeignKey(Propertytype, related_name='propertytype')
    date = models.DateTimeField(null=True, blank=True)
    followup_date = models.DateTimeField(null=True, blank=True)
    quantity = models.PositiveSmallIntegerField()


    def __str__(self):
        return self.propertytype

    def clean(self):
        model = self.__class__
        if  (self.unit) and model.objects.filter(unit=self.unit, propertytype=self.propertytype ).exclude(id=self.id).count() == 1:
            raise ValidationError('Same property cant be assigned more then ones')

对于这个模型,我有表格

class Property1Form(forms.ModelForm):

    class Meta:
        model = Property1
        fields = ['unit','propertytype','is_true','date','followup_date','quantity','description']

    def __init__(self, *args, **kwargs):
        super(Property1Form, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance:
            self.fields['unit'].required = False
            self.fields['unit'].widget.attrs['disabled'] = 'disabled'

我有一个观点

def property_new(request,pk,uri):
    unit = get_object_or_404(Unit, pk=pk)
    title = 'property'
    uri = _get_redirect_url(request, uri)
    if request.method == "POST":
        form = Property1Form(request.POST)
        form.unit = unit


        if form.is_valid():
            properties = form.save(commit=False)
            properties.unit = unit 

            properties.save()
            messages.add_message(request, messages.SUCCESS, str(properties.unit) + "-SUCCESS Object created sucssefully")

            return redirect(uri)
    else:
        form = Property1Form(initial={'unit': unit})


    return render(request, 'object_edit.html', {'form': form, 'title':title, 'extend': EXTEND})

然而,在创建新属性后,我总是得到

  

*** Property1的RelatedObjectDoesNotExist没有单位。

执行

期间触发错误
  if form.is_valid(): 

有什么问题?

更新:

回溯:

File "C:\Users\Boris\dev\rentout\virtrentout\lib\site-packages\django\core\handlers\base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Boris\dev\rentout\rentout\unit\views.py" in property_new
  390.         if form.is_valid():
File "C:\Users\Boris\dev\rentout\virtrentout\lib\site-packages\django\forms\forms.py" in is_valid
  184.         return self.is_bound and not self.errors
File "C:\Users\Boris\dev\rentout\virtrentout\lib\site-packages\django\forms\forms.py" in errors
  176.             self.full_clean()
File "C:\Users\Boris\dev\rentout\virtrentout\lib\site-packages\django\forms\forms.py" in full_clean
  394.         self._post_clean()
File "C:\Users\Boris\dev\rentout\virtrentout\lib\site-packages\django\forms\models.py" in _post_clean
  430.             self.instance.full_clean(exclude=exclude, validate_unique=False)
File "C:\Users\Boris\dev\rentout\virtrentout\lib\site-packages\django\db\models\base.py" in full_clean
  1132.             self.clean()
File "C:\Users\Boris\dev\rentout\rentout\unit\models.py" in clean
  117.         if  (self.unit) and model.objects.filter(unit=self.unit, propertytype=self.propertytype ).exclude(id=self.id).count() == 1:
File "C:\Users\Boris\dev\rentout\virtrentout\lib\site-packages\django\db\models\fields\related.py" in __get__
  608.                 "%s has no %s." % (self.field.model.__name__, self.field.name)

Exception Type: RelatedObjectDoesNotExist at /unit/property/new/6/http://127.0.0.1:8000/unit/property_details/6/
Exception Value: Property1 has no unit.

1 个答案:

答案 0 :(得分:1)

设置required=False并禁用小部件并不理想。禁用窗口小部件意味着您的浏览器不会为该字段提交任何值。由于您有required=False,这意味着表单会将外键设置为None。但是,这与模型的外键不兼容,该外键默认为null=False

我对内部不熟悉以准确解释异常,但基本问题是Django在表单将外键设置为{之后尝试从数据库中获取相关的unit {1}}。

一种解决方法是检查None而不是self.unit_id。这可以防止数据库查找,因此您不会获得异常。

然而,这对我来说似乎有点脏。如果您不希望用户编辑self.unit字段,我会将其从表单中完全删除。检查unit以确定实例是否已在数据库中。

self.instance.pk

然后在您看来,您不必再设置def __init__(self, *args, **kwargs): super(Property1Form, self).__init__(*args, **kwargs) if self.instance.pk: del self.fields['unit'] 了。我也会删除properties.unit = unit,我认为它不会有用。