这是此SO question的扩展。
是否有一种简单的方法可以动态生成所需的clean_X方法,以确保不会修改只读表单字段?我可以按照链接问题的建议手动编写方法,但是当你有多个需要以只读方式创建的字段的形式时,新颖性会很快消失。
必须有更好的方法!
解决方案:
根据提供的答案,我决定只覆盖基类中的Form.clean()
方法。这是我的表单继承的类,它接受一个参数read_only
,它是一个实例属性列表作为字符串。
class FormBase(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.read_only = kwargs.pop("read_only", [])
super(FormBase, self).__init__(*args, **kwargs)
#Disable any read only controls
for f in self.read_only:
self.fields[f].widget.attrs["readonly"] = True
def clean(self):
cleaned_data = super(FormBase, self).clean()
for f in self.read_only:
cleaned_data[f] = getattr(self.instance, f)
return cleaned_data
答案 0 :(得分:3)
请注意,验证不仅限于form.clean_*
方法 - 您也可以使用form.clean()
并将cleaned_data
值还原为初始实例属性值。如果您在类中定义只读字段的列表(或将其作为参数或其他方式传递),则只需迭代此列表即可重置您的值。
现在你真的坚持动态定义clean_*
方法,这里有未经测试,过度简化和完全丑陋的可能解决方案:
class MyForm(...):
readonly_fields = ("afield", "another",)
def __init__(self, *args, **kw):
super(MyForm, self).__init__(*args, **kw)
for field in self.readonly_fields:
self.fields[field].widget.attrs['readonly']
def clean(field=field):
# assume fieldname == instance attribute name
return getattr(self.instance, field)
setattr(self, "clean_%s" % field, clean)
显然,使用Form.clean
更容易,更易读,方式更难看。