2

这是对这个 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
4

1 回答 1

4

请注意,验证不仅限于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更容易,更易读,而且那么难看。

于 2013-04-08T15:09:22.990 回答