我有一个要更新MyModel对象的表单。在模型上,存在一个unique_together约束,即fieldA和fieldB。在clean方法的表单中,我检查此唯一约束。

由于某些原因,我必须在更新中将fieldA显示为只读。因此,fieldA没有通过。我的问题是,如果表单未通过验证,则会重新显示该表单,但是我丢失了fieldA中的值。

我试图重置cleaned_data ['fieldA'],但是它不起作用。
知道要更改什么吗?

Forms.py

class MyModelUpdateForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(MyModelUpdateForm, self).__init__(*args, **kwargs)
        self.fields['fieldA'].widget.attrs['readonly'] = True
        self.fields['fieldA'].widget.attrs['disabled'] = True

    def clean(self):
        cleaned_data = self.cleaned_data
        fieldA= self.instance.fieldA
        fieldB = cleaned_data.get("fieldB")

        if MyModel.objects.filter(fieldA=fieldA, fieldB=fieldB).count() > 0:
            #try to reset fieldA, since it is not passed through, since it is disabled
            cleaned_data['fieldA'] = fieldA.pk #does not work
            raise forms.ValidationError('some unique validation error')
        return cleaned_data


Views.py:

myModelobject = get_object_or_404(MyModel.objects, pk=mymodel_id)

    if request.method == 'POST':
        model_form = MyModelUpdateForm(request.POST, instance=myModelobject )

        if model_form .is_valid():
           ....

最佳答案

对于表格的工作原理,我感到很有趣,并想出了多种解决方案,仅此而已。

由于禁用的是窗口小部件而不是字段,因此就表单而言,它始终不会为fieldA接收任何内容,并且始终会导致验证失败。

在clean()方法中尝试某些操作对无效表单无济于事,因为clean()数据用于处理。

看起来用于HTML显示的表单提取数据的方式是field.data,这是对field.widget.value_from_datadict(POST, FILES, field_name)的调用,因此它将始终查看您的POST数据。

所以我认为您有一些选择。破解request.POST,破解内部表单POST数据或破解value_from_datadict



破解request.POST:直截了当,很有意义。

    myModelobject = get_object_or_404(MyModel.objects, pk=mymodel_id)

        if request.method == 'POST':
            POST = request.POST.copy()
            POST['fieldA'] = myModelobject.fieldA
            model_form = MyModelUpdateForm(POST, instance=myModelobject )

            if model_form .is_valid():
                # ...


入侵内部字典:

def __init__(self, *args, **kwargs):
    super(MyModelUpdateForm, self).__init__(*args, **kwargs)
    self.data.update({ 'fieldA': self.instance.fieldA })


黑客value_from_datadict:有点荒谬,但是说明了您可以从源代码中学习到什么

def __init__(self, *args, **kwargs):
    super(MyModelUpdateForm, self).__init__(*args, **kwargs)
    self.fields['fieldA'].widget.value_from_datadict = lambda *args: self.instance.first_name


在这里学到了一些很酷的东西:)希望对您有所帮助。

10-06 02:03