Django 表单、表单字段的继承和顺序 [英] Django forms, inheritance and order of form fields

查看:35
本文介绍了Django 表单、表单字段的继承和顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的网站中使用了 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆