Django ModelForm-如何使表单生成不可编辑

时间:2013-07-08 06:04:59

标签: django django-forms

我正在学习django形式,并想知道如何使模型表单仅生成显示。

models.py

class Person(models.Model):
    first_name = models.CharField(max_length=40, null=True)
    last_name = models.CharField(max_length=40, null=True)
    #more fields

forms.py

class PersonForm(ModelForm):
    class Meta:
        model = Person

要生成包含数据库中某些现有数据的表单:

person=Person.objects.get(id=someid)
person_form = PersonForm(instance = person)

表单中的所有字段都可在页面中编辑。但是,我只是想显示数据。

在StackOverflow中进行了一些搜索之后,我发现了一个类似的解决方案how to show a django ModelForm field as uneditable,它教会了如何设置单个字段

但我想让整个表格无法编辑。有没有更好的方法,而不是将所有字段逐个设置为不可编辑?

非常感谢你的帮助。

更新:我发现流动的代码有助于使表单无法使用,但仍不确定这是否是正确的方法。

for field in person_form.fields:
            person_form.fields[field].widget.attrs['readonly'] = True

感谢您的建议。

4 个答案:

答案 0 :(得分:1)

表单上没有名为editable或类似内容的属性,可以对所有字段执行操作。所以,你不能在表单层面上这样做。

此外,django表单中使用的Field类也没有此类属性,因此无法设置此类属性并使该字段为只读。因此,您必须对表单__init__中表单的字段进行操作。

class PersonForm(ModelForm):
    class Meta:
        model = Person

    def __init__(self, *args, **kwargs):
        super(PersonForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.iteritems():
            field.widget.attrs['readonly'] = 'true'

如果您只想使某些字段不可编辑,请更改__init__

    def __init__(self, *args, **kwargs):
        super(PersonForm, self).__init__(*args, **kwargs)
        uneditable_fields = ['first_name', 'last_name']
        for field in uneditable_fields:
            self.fields[field].widget.attrs['readonly'] = 'true'

答案 1 :(得分:1)

也许另一个解决方案,不必做任何处理,只需显示这样..

<table border='1'>
    {% for field in form%}
        <tr>
            <td>{{field.label}}</td>
            <td>{{field.value}}</td>
        </tr>

    {% endfor%}

</table>

答案 2 :(得分:0)

我知道,老问题,但由于本周我有同样的问题,这可能对其他人有所帮助。 此技术仅在您希望整个表单只读时才有效。它会覆盖任何发布的数据(请参阅def clean(self))并将窗口小部件属性设置为只读。

注意:将窗口小部件属性设置为readonly不会阻止更改模型对象实例。

class MyModelForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)

        if self.is_readonly():
            for k,f in self.fields.iteritems():
                f.widget.attrs['readonly'] = True

    def clean(self):
        if self.is_readonly():
                return {}
        return super(CompanyQuestionUpdateForm, self).clean()

    def is_readonly(self, question):
        if your_condition:
            return True
        return False

    class Meta:
        model = MyModel

答案 3 :(得分:0)

可以实现字段小部件来呈现包含在div或td中的绑定ModelForm字段值,示例实现是否存在

https://github.com/Dmitri-Sintsov/django-jinja-knockout/blob/master/django_jinja_knockout/widgets.py

# Read-only widget for existing models.
class DisplayText(Widget):

然后可以实现一个表单元类,它将自动为所有ModelForm字段设置字段小部件为DisplayText:

https://github.com/Dmitri-Sintsov/djk-sample/search?utf8=%E2%9C%93&q=DisplayModelMetaclass

class ClubDisplayForm(BootstrapModelForm, metaclass=DisplayModelMetaclass):

    class Meta(ClubForm.Meta):
        widgets = {
            'category': DisplayText()
        }

随意使用或开发自己的小部件/窗体元类版本。

有关django bug票证的只读ModelForms的讨论:

https://code.djangoproject.com/ticket/17031

关闭为“Froms用于处理数据,而不是渲染数据。”

但我认为这是错误的原因:

  • ModelForms不仅处理数据,还将表单映射到模型。只读映射是映射的子集。

  • 内联表单集和只读内联表单集更加方便,手动渲染关系会带来很多负担。

  • 基于类的视图可以共享公共模板以显示和编辑ModelForms。因此只读显示ModelForms会增加DRY(Django关键原则之一)。