Django使用小部件创建只读表单字段

17 投票
4 回答
39277 浏览
提问于 2025-04-15 16:34

我的表单字段大概是这样的:

class FooForm(ModelForm):
    somefield = models.CharField(
        widget=forms.TextInput(attrs={'readonly':'readonly'})
    )

    class Meta:
        model = Foo

我在上面的代码中遇到了一个错误,内容是:init() 收到了一个意外的关键字参数 'widget'

我以为这是对表单小部件的合理使用呢?

4 个回答

5

我之前也遇到过同样的问题,所以我创建了一个混合类(Mixin),它似乎适合我的使用场景。

class ReadOnlyFieldsMixin(object):
    readonly_fields =()

    def __init__(self, *args, **kwargs):
        super(ReadOnlyFieldsMixin, self).__init__(*args, **kwargs)
        for field in (field for name, field in self.fields.iteritems() if name in self.readonly_fields):
            field.widget.attrs['disabled'] = 'true'
            field.required = False

    def clean(self):
        cleaned_data = super(ReadOnlyFieldsMixin,self).clean()
        for field in self.readonly_fields:
           cleaned_data[field] = getattr(self.instance, field)

        return cleaned_data

使用方法很简单,只需要定义哪些属性是只读的:

class MyFormWithReadOnlyFields(ReadOnlyFieldsMixin, MyForm):
    readonly_fields = ('field1', 'field2', 'fieldx')
20

请注意,readonly 属性并不能阻止 Django 处理客户端发送的任何值。如果你希望这个值不被改变,无论用户用什么花招(比如使用 FireBug),那么你需要使用更复杂的方法,比如使用 ReadOnlyFieldReadOnlyWidget,就像在 Alex Gaynor 的一篇 博客文章 中演示的那样。

45

你应该使用表单字段,而不是模型字段:

somefield = models.CharField(
    widget=forms.TextInput(attrs={'readonly': 'readonly'})
)

替换为

somefield = forms.CharField(
    widget=forms.TextInput(attrs={'readonly': 'readonly'})
)

这样应该能解决问题。

撰写回答