当前位置:  开发笔记 > 编程语言 > 正文

Django如何知道渲染表单字段的顺序?

如何解决《Django如何知道渲染表单字段的顺序?》经验,为你挑选了7个好方法。

如果我有一个Django表格,例如:

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    sender = forms.EmailField()

我调用此表单实例的as_table()方法,Django将按照上面指定的顺序呈现字段.

我的问题是Django如何知道定义类变量的顺序?

(另外我如何覆盖这个顺序,例如当我想从classe的init方法中添加一个字段?)



1> holdenweb..:

[注意:这个答案现在已经过时了 - 请参阅下面的讨论,以及最近的答案].

如果f是一种形式,它的领域是f.fields,这是一个django.utils.datastructures.SortedDict (它呈现它们被添加的顺序选择项目).在表单构造之后,f.fields有一个keyOrder属性,该属性是一个包含字段名称的列表,按顺序显示它们.您可以将其设置为正确的顺序(尽管您需要注意确保不要省略项目或添加额外内容).

这是我刚才在当前项目中创建的一个示例:

class PrivEdit(ModelForm):
    def __init__(self, *args, **kw):
        super(ModelForm, self).__init__(*args, **kw)
        self.fields.keyOrder = [
            'super_user',
            'all_districts',
            'multi_district',
            'all_schools',
            'manage_users',
            'direct_login',
            'student_detail',
            'license']
    class Meta:
        model = Privilege


一段时间以来,字段将按照ModelForm的"fields"属性的指定进行排序.来自https://docs.djangoproject.com/en/1.3/topics/forms/modelforms/#using-a-subset-of-fields-on-the-form:在该列表中指定字段名称的顺序表单呈现时会受到尊重.这仅适用于ModelForms - 您的方法对于常规表单仍然非常有用,尤其是在添加其他字段的表单子类中.
当你正在做一些覆盖某些领域而不是其他领域的时髦东西时,这种方法很有效.+1

2> Steve Tjoa..:

Django 1.9的新功能是Form.field_orderForm.order_fields().

# forms.Form example
class SignupForm(forms.Form):

    password = ...
    email = ...
    username = ...

    field_order = ['username', 'email', 'password']


# forms.ModelForm example
class UserAccount(forms.ModelForm):

    custom_field = models.CharField(max_length=254)

    def Meta:
        model = User
        fields = ('username', 'email')

    field_order = ['username', 'custom_field', 'password']


注意:不是“ fields_order”,而是“ field_order”(没有's')

3> Greg..:

我继续前进并回答了我自己的问题.以下是未来参考的答案:

在Django form.py中,使用该__new__方法将类变量最终加载到类self.fields中定义的顺序中. self.fields是一个Django SortedDict实例(在中定义datastructures.py).

所以要覆盖它,比如在我的例子中你希望发送者先来但需要在init方法中添加它,你会这样做:

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    def __init__(self,*args,**kwargs):
        forms.Form.__init__(self,*args,**kwargs)
        #first argument, index is the position of the field you want it to come before
        self.fields.insert(0,'sender',forms.EmailField(initial=str(time.time())))


你可以在顶部正常定义'sender'字段,然后在你的插入行上使用一个变体:`self.fields.insert(0,'sender',self.fields ['sender'])`
这不再适用于Django 1.7,因为表单字段使用不支持追加的OrderedDict.请参阅下面的更新答案(评论太长)...

4> 小智..:

字段按ModelClass._meta.fields中定义的顺序列出.但是如果要在Form中更改顺序,可以使用keyOrder函数.例如 :

class ContestForm(ModelForm):
  class Meta:
    model = Contest
    exclude=('create_date', 'company')

  def __init__(self, *args, **kwargs):
    super(ContestForm, self).__init__(*args, **kwargs)
    self.fields.keyOrder = [
        'name',
        'description',
        'image',
        'video_link',
        'category']



5> Zulu..:

使用Django> = 1.7,您必须修改ContactForm.base_fields如下:

from collections import OrderedDict

...

class ContactForm(forms.Form):
    ...

ContactForm.base_fields = OrderedDict(
    (k, ContactForm.base_fields[k])
    for k in ['your', 'field', 'in', 'order']
)

这个技巧用于Github上的 Django Admin PasswordChangeForm:Source


有趣的是,当我试图弄清楚为什么子类化`PasswordChangeForm`改变了字段的顺序时,我寻找字段的排序,所以你的例子碰巧对我非常有用.这似乎是因为`base_fields`没有被转移到子类.解决方案似乎在`PasswordChangeFormSubclass定义之后说'PasswordChangeFormSubclass.base_fields = PasswordChangeForm.base_fields`

6> zgoda..:

表单字段具有创建顺序的属性,称为creation_counter..fields属性是一个字典,所以简单地添加到字典和更改creation_counter所有字段中的属性以反映新的排序应该足够了(尽管从未尝试过这个).



7> nosklo..:

在Field类中使用计数器.按该计数器排序:

import operator
import itertools

class Field(object):
    _counter = itertools.count()
    def __init__(self):
        self.count = Field._counter.next()
        self.name = ''
    def __repr__(self):
        return "Field(%r)" % self.name

class MyForm(object):
    b = Field()
    a = Field()
    c = Field()

    def __init__(self):
        self.fields = []
        for field_name in dir(self):
            field = getattr(self, field_name)
            if isinstance(field, Field):
                field.name = field_name
                self.fields.append(field)
        self.fields.sort(key=operator.attrgetter('count'))

m = MyForm()
print m.fields # in defined order

输出:

[Field('b'), Field('a'), Field('c')]

推荐阅读
mobiledu2402852413
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有