2

我正在学习 django 表单,并且想知道如何仅制作模型表单生成的显示。

模型.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

表格.py

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

要使用数据库中的一些现有数据生成表单:

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

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

在 StackOverflow 中进行了一些搜索后,我找到了一个类似的解决方案,如何将 django ModelForm 字段显示为 uneditable,它教授如何设置单个字段不可编辑。

但我想让整个表单无法编辑。有没有更好的方法来代替将所有字段一一设置为不可编辑?

非常感谢您的帮助。

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

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

谢谢你的建议。

4

4 回答 4

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'
于 2013-07-08T09:14:07.933 回答
1

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

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

    {% endfor%}

</table>
于 2013-07-09T03:49:34.957 回答
0

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

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

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
于 2014-06-30T13:23:55.003 回答
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 ticket 中有关于只读 ModelForms 的讨论:

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

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

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

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

  • 有内联表单集,并且具有只读的内联表单集更加方便,它为手动渲染关系留下了很多负担。

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

于 2016-10-18T13:19:11.967 回答