您的位置:

对于django错误FieldError("'%s' cannot be specified for %s model form as it is a ""non-editable field" % (f.name, model.__name__))的解决

  发布时间:2023-03-30 12:15:15
报错的原因这个错误通常是在使用Django中的ModelForm时出现的。你的模型中的字段是自动生成的,例如,使用了`auto_now=True`或`auto_now_add=True`选项。你在使用ModelForm类时,在Meta类中未包括一些字段或多了一些字段。例如,你可以重载`clean_fieldname`方法来添加额外的验证规则。例如在MyModel中有一个hidden_field字段,你可以这样定义这样,即使表单里没有hidden_field字段,在保存表单后MyModel的hidden_field字段仍然有值。这个例子中的 clean() 方法可以使 hidden_field 字段的值为 “hidden value”,并且在表单提交时不会抛出任何错误。

报错的原因

这个错误通常是在使用Django中的ModelForm时出现的。它表示你正在尝试在表单中编辑一个不可编辑的字段。

这个错误可能是由于以下原因之一导致的:

1. 你的模型中的字段被定义为只读,例如,使用了`editable=False`选项。

2. 你的模型中的字段是自动生成的,例如,使用了`auto_now=True`或`auto_now_add=True`选项。

3. 你在使用ModelForm类时,在Meta类中未包括一些字段或多了一些字段。

解决办法是在你的ModelForm类中添加/删除对应的字段,或在模型中将字段设置为可编辑。

如何解决

解决这个问题最简单的办法就是在你的ModelForm中添加/删除对应的字段,使得它和你的模型字段一致。

例如:


class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['field1', 'field2', 'field3']

如果你的model中的字段不可编辑的话,还需要将可编辑的字段添加进去,可以这样做:


class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['field1', 'field2', 'field3']
        exclude = ['non_editable_field']

如果你需要自定义字段选项或验证,你可以在表单类中重新定义字段。

如果这个表单需要一个新字段,则需要在表单类中手动添加一个字段。

当然你也可以根据需求重载函数来改变字段规则。

是的,除了上面提到的添加/删除字段,你还可以重载ModelForm中的一些方法来更改字段的行为。

例如,你可以重载`clean_fieldname`方法来添加额外的验证规则。或者你可以重载`save`方法来添加额外的逻辑在保存对象之前或之后。

如果你的字段是自动生成的,例如,使用了`auto_now=True`或`auto_now_add=True`选项,你可以重写`save()`方法来在保存对象之前先将这些字段的值清空,或者在更新对象之前先将这些字段的值更新。

另外在使用Modelform时,可以在view中对字段进行只读或隐藏操作,也可以通过为字段设置属性,来更改字段的样式,这样解决了在Model中进行修改的麻烦。

总之,还需要根据需求和问题的具体情况来确定你采取的解决办法。

使用例子

当然可以,这里举个例子,假设你有一个模型`MyModel`,其中一个字段是`updated_at`,设置了`auto_now=True`选项,即在更新模型对象时自动更新时间。

你可以重写MyModelForm的save方法来解决这个问题


class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['field1', 'field2', 'field3']

    def save(self, commit=True):
        instance = super().save(commit=False)
        instance.updated_at = None
        if commit:
            instance.save()
        return instance

这样就在保存对象之前先将updated_at字段的值清空了,这个字段就不会自动更新了。

另外如果你想在表单中禁用一个字段或隐藏一个字段,可以在你的view中这样写,对一个字段设置为只读:


form = MyModelForm()
form.fields['field1'].widget.attrs['readonly'] = True

隐藏一个字段:


form = MyModelForm()
form.fields['field1'].widget = forms.HiddenInput()

希望这个例子能帮到你理解,如果有其他疑问可以随时问

如果你想在表单里隐藏一个字段并且保存这个字段的值,可以在modelform中重载clean方法。

例如在MyModel中有一个hidden_field字段,你可以这样定义:


class MyModelForm(forms.ModelForm):
    hidden_field = forms.CharField(widget=forms.HiddenInput, required=False)

    class Meta:
        model = MyModel
        fields = ['field1', 'field2', 'field3']
    def clean(self):
        cleaned_data = super().clean()
        if 'hidden_field' in self.cleaned_data:
            self.cleaned_data['hidden_field'] = "hidden value"
        return cleaned_data

这样,即使表单里没有hidden_field字段,在保存表单后MyModel的hidden_field字段仍然有值。

这个例子中的 clean() 方法可以使 hidden_field 字段的值为 “hidden value”,并且在表单提交时不会抛出任何错误。这样就可以在使用ModelForm的同时隐藏字段并且不丢失这个字段的值了。

如果你有其他疑问,请随时问我。