重新排列模型表单字段

7

我需要重新排列一个来自其他基类的模型表单中的字段。找不到解决方法。下面代码片段中的“地址”始终出现在HTML模板的开头。如何将其移动到渲染模板中的更下方?谢谢。

class Address:
   street= ...
   city= ...

class Customer(Address):
   name = ...
   ...

class CustomerForm(ModelForm):
   def __init__(...)
        super(CustomerForm, self).__init__(*args, **kw)
        self.fields.keyOrder=[
        'name',
        'Address',  #<-- I want "Address" appear after the name in my template
                    #<-- This obviously is not the right code.
   class Meta:
      model = Customer

-P

5个回答

10
在Django 1.9中,他们为Form类添加了一个新参数,现在你可以通过定义field_order来更改顺序,例如将两个字段添加到userena应用程序表单中:

在Django 1.9中,他们为Form类添加了一个新的参数。现在,您可以通过定义field_order来改变顺序。例如,在userena应用程序表单中添加两个字段:

class SignupFormExtra(SignupForm):
    """
    A form to demonstrate how to add extra fields to the signup form, in this
    case adding the first and last name.
    """
    first_name = forms.CharField(label=_(u'First name'),
                             max_length=30,
                             required=False)

    last_name = forms.CharField(label=_(u'Last name'),
                            max_length=30,
                            required=False)
    field_order=['first_name','last_name']

您可以将其用于继承类 Form 的任何表单。

默认情况下,Form.field_order=None,这将保留您在表单类中定义字段的顺序。如果field_order是字段名称列表,则按照列表指定的顺序排序字段,并根据默认顺序附加其余字段。


谢谢!它完全按照你描述的方式工作。我正在使用Django 1.11。 - Julia Zhao

7
重新排序非常繁琐:
# django's SortedDict stores ordering of its fields in this list-type attribute:
keyorder = self.fields.keyOrder

# Remove fields which we want to displace:
keyorder.remove('street')
keyorder.remove('city')

# Get position where we want them to put in:
i = keyorder.index('name') + 1

# Insert items back into the list:
keyorder[i:i] = ['city', 'street']

最好的方式可能是再按正确的顺序列出所有字段:
class MyForm(ModelForm):
    class Meta:
       model=Customer
       fields=[..., 'name', 'street', 'city', ...]

谢谢Skirmantas!我尝试了第二种方法,它非常好用。我之前尝试过像“name”,“Address.street”这样的方式...非常感谢您的时间。 - pdxMobile

6
from django import forms

class CustomForm(forms.Form):
    ORDER = ('field1', 'field2', 'field3')
    def __init__(self, *args, **kwargs):
        super(CustomForm, self).__init__(*args, **kwargs)
        fields = OrderedDict()
        for key in self.ORDER:
            fields[key] = self.fields.pop(key)
        self.fields = fields

1
欢迎来到SO并感谢您发布答案。请考虑为您的代码发布上下文。 - Richard Erickson
使用此代码的人请记得导入 from collections import OrderedDict - sgauri

2

当我们升级到Django 1.7后,Skyjur使用的.keyOrder停止工作了(现在Django使用collections.OrderedDict)。因此,我不得不找到一个解决方法,以下是我目前正在使用的方法:

from collections import OrderedDict
...
class MyForm(forms
    def __init__(self, *args, **kwargs):
        fields = OrderedDict()
        for key in ("my_preferred_first_field", "my_preferred_second_field"):
            fields[key] = self.fields.pop(key)
        for key, value in self.fields.items():
            fields[key] = value
        self.fields = fields

1
在较新的Django中,fields属性是一个collections.OrderedDict,自Python 3.2以来有一个新方法move_to_end,因此您可以简单地执行以下操作:
class CustomForm(forms.Form):

    ...

    # Note the following must contain all the fields in the form in the order
    # you desire.
    CUSTOM_ORDER = ('field1', 'field2', 'field3')

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

        # Use custom order for form fields.
        for field_name in CUSTOM_ORDER:
            self.fields.move_to_end(field_name)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接