Django 表单、表单字段的继承和顺序 [英] Django forms, inheritance and order of form fields
问题描述
我在我的网站中使用了 Django 表单并且想要控制字段的顺序.
I'm using Django forms in my website and would like to control the order of the fields.
以下是我定义表单的方式:
Here's how I define my forms:
class edit_form(forms.Form):
summary = forms.CharField()
description = forms.CharField(widget=forms.TextArea)
class create_form(edit_form):
name = forms.CharField()
名称是不可变的,仅应在创建实体时列出.我使用继承来添加一致性和 DRY 原则.实际上完全可以预料到的情况是,名称字段列在视图/html 的最后,但我希望名称字段位于摘要和描述之上.我确实意识到我可以通过将摘要和描述复制到 create_form 并取消继承来轻松修复它,但我想知道这是否可行.
The name is immutable and should only be listed when the entity is created. I use inheritance to add consistency and DRY principles. What happens which is not erroneous, in fact totally expected, is that the name field is listed last in the view/html but I'd like the name field to be on top of summary and description. I do realize that I could easily fix it by copying summary and description into create_form and loose the inheritance but I'd like to know if this is possible.
为什么? 假设您在 edit_form 中有 100 个字段,并且必须在 create_form 的顶部添加 10 个字段 - 复制和维护这两个表单看起来不会那么性感.(这不是我的情况,我只是举个例子)
Why? Imagine you've got 100 fields in edit_form and have to add 10 fields on the top in create_form - copying and maintaining the two forms wouldn't look so sexy then. (This is not my case, I'm just making up an example)
那么,我该如何覆盖这种行为?
So, how can I override this behavior?
显然,没有经过讨厌的黑客攻击(摆弄 .field 属性),就没有正确的方法可以做到这一点..field 属性是一个 SortedDict(Django 的内部数据结构之一),它不提供任何重新排序键值对的方法.它确实提供了一种在给定索引处插入项目的方法,但这会将项目从类成员移动到构造函数中.这种方法可以工作,但会使代码的可读性降低.我认为合适的唯一其他方法是修改框架本身,这在大多数情况下都不是最佳的.
Apparently there's no proper way to do this without going through nasty hacks (fiddling with .field attribute). The .field attribute is a SortedDict (one of Django's internal datastructures) which doesn't provide any way to reorder key:value pairs. It does how-ever provide a way to insert items at a given index but that would move the items from the class members and into the constructor. This method would work, but make the code less readable. The only other way I see fit is to modify the framework itself which is less-than-optimal in most situations.
简而言之,代码会变成这样:
In short the code would become something like this:
class edit_form(forms.Form):
summary = forms.CharField()
description = forms.CharField(widget=forms.TextArea)
class create_form(edit_form):
def __init__(self,*args,**kwargs):
forms.Form.__init__(self,*args,**kwargs)
self.fields.insert(0,'name',forms.CharField())
那让我闭嘴:)
推荐答案
来自 Django 1.9+
Django 1.9 添加了一个新的 Form
属性,field_order
,允许对字段进行排序,而不管它们在类中的声明顺序.
From Django 1.9+
Django 1.9 adds a new Form
attribute, field_order
, allowing to order the field regardless their order of declaration in the class.
class MyForm(forms.Form):
summary = forms.CharField()
description = forms.CharField(widget=forms.TextArea)
author = forms.CharField()
notes = form.CharField()
field_order = ['author', 'summary']
field_order
中缺少的字段保持它们在类中的顺序,并附加在列表中指定的字段之后.上面的示例将按以下顺序生成字段:['author', 'summary', 'description', 'notes']
Missing fields in field_order
keep their order in the class and are appended after the ones specified in the list. The example above will produce the fields in this order: ['author', 'summary', 'description', 'notes']
查看文档:https://docs.djangoproject.com/en/stable/ref/forms/api/#notes-on-field-ordering
我遇到了同样的问题,我在 Django CookBook 中找到了另一种重新排序字段的技术:
I had this same problem and I found another technique for reordering fields in the Django CookBook:
class EditForm(forms.Form):
summary = forms.CharField()
description = forms.CharField(widget=forms.TextArea)
class CreateForm(EditForm):
name = forms.CharField()
def __init__(self, *args, **kwargs):
super(CreateForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = ['name', 'summary', 'description']
这篇关于Django 表单、表单字段的继承和顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!