【问题标题】:django forms set field orderdjango 表单设置字段顺序
【发布时间】:2015-02-17 18:16:44
【问题描述】:

我正在尝试设置表单的字段顺序。但不知何故,它只是按字母顺序排列。有人有什么建议吗?我尝试了 class Meta: fields = ["field", "field"] 并在 init

中添加了一个 keyOrder

表格:

class HangarFilterForm(forms.Form):

    FIELDS = [
        ("", ""),
        ("warp", "Warp"),
        ("cargo_space", "Cargo Space"),
        ("smuggle_bay", "Smuggle Bay"),
        ("dock", "Dock/Undock"),
        ("enter_warp", "Enter Warp"),
        ("fuel_bay", "Fuel Bay"),
        ("fuel_cost", "Fuel Cost"),
    ]

    PER_PAGE = [
        (10, ""),
        (5, "5 ships"),
        (10, "10 ships"),
        (25, "25 ships"),
        (50, "50 ships"),
    ]

    field_1 = forms.ChoiceField(choices=FIELDS, label="1st attribute", required=False)
    field_2 = forms.ChoiceField(choices=FIELDS, label="2nd attribute", required=False)
    per_page = forms.ChoiceField(choices=PER_PAGE, required=False)

    def __init__(self, *args, **kwargs):
        super(HangarFilterForm, self).__init__(*args, **kwargs)
        self.fields['planet'] = forms.ChoiceField(
                        choices=[("", "")] + [ (o.id, o.name) for o in    lanet.objects.all().order_by("name")], 
                        required=False)
        self.fields['type'] = forms.ChoiceField(
                        choices=[("", "")] + [ (o[0], o[1]) for o in ShipTemplate.SHIP_TYPES], required=False)
        self.fields.keyOrder = ["planet", "type", "field_1", "field_2", "per_page"]

【问题讨论】:

    标签: django forms field


    【解决方案1】:

    在 Django 1.9 中,添加了强制表单字段顺序的新方法:field_order

    看一看(链接到 1.9 版): https://docs.djangoproject.com/en/1.9/ref/forms/api/#django.forms.Form.field_order

    (以及开发版本的链接): https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.field_order

    在下面找到一个简短的示例(使用 Django 1.9)

    models.py:

    from django.db import models
    
    class Project(models.Model):
         end_date = models.DateField(verbose_name='End date',
                                    blank=True)
    
        start_date = models.DateField(verbose_name='Start date',
                                      blank=True)
    
        title = models.CharField(max_length=255,
                                 blank=False,
                                 verbose_name='Title')
    
        def __str__(self):
            return self.title
    

    forms.py

    from django.forms import ModelForm, DateTimeField, SelectDateWidget
    
    from XXX.models import Project
    
    class ProjectForm(ModelForm):
        class Meta:
            model = Project
            fields = '__all__'
    
        start_date = DateTimeField(widget=SelectDateWidget)
        end_date = DateTimeField(widget=SelectDateWidget)
    
        field_order = ['start_date', 'end_date']
    

    在此示例中,字段将重新排列为:

    1. start_date
    2. end_date
    3. 标题

    【讨论】:

      【解决方案2】:

      这是我过去所做的一些代码,用于在有效的表单中重新排列字段顺序;您可能可以将其放入 mixin 以在其他地方使用。告诉我进展如何。

      from django.utils.datastructures import SortedDict
      
      
      class HangarFilterForm(forms.Form):
      
          ordered_field_names = ['planet', 'type', 'field_1', 'field_2', 'per_page']
      
          def __init__(self, *args, **kwargs):
              super(HangarFilterForm, self).__init__(*args, **kwargs)
              # Your field initialisation code
              self.rearrange_field_order()
      
          def rearrange_field_order(self):
      
              original_fields = self.fields
              new_fields = SortedDict()
      
              for field_name in self.ordered_field_names:
                  field = original_fields.get(field_name)
                  if field:
                      new_fields[field_name] = field
      
              self.fields = new_fields
      

      如果您出于某种原因想要跟踪原始文件顺序,只需将rearrange_field_order 中的original_fields 更改为self.original_fields

      【讨论】:

      • 似乎工作得很好。谢谢 :) 至少我现在可以循环我的表单,而不是手动设置每个表单字段:)
      【解决方案3】:

      我尝试在 django 2.1 的 Meta 部分表单中设置 fields,它也成功了:

      class MyForm(forms.ModelForm):
          ...
      
          class Meta:
              model = Contact
              fields = ('field_1', 'field_2', 'field_3', 'field_4',)
      

      【讨论】:

        【解决方案4】:

        可能有点跑题了。使用django crispy formstheir Layout objects 可以帮助您按照您想要的方式格式化表单。其中包括重新排列字段顺序。

        举例说明:

        class UpdateUserForm(forms.ModelForm):
        
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
                self.helper = FormHelper()
                self.helper.layout = Layout(
                    Field('email'),
                    Field('quote'),
                    Field('website', placeholder="http://"),
                    Field('logo', template="user/logoInput.html"),
                    HTML('<label class="control-label">Other settings</label>'),
                    Field('emailVisible'),
                    Field('subscribeToEmails'),
                    Field('mpEmailNotif'),
                    Field('showSmileys'),
                    Field('fullscreen'),
                )
        
            class Meta:
                model = ForumUser
                fields = ('email', 'emailVisible', 'subscribeToEmails', 'mpEmailNotif',
                          'logo', 'quote', 'website', 'showSmileys', 'fullscreen')
        

        【讨论】:

          【解决方案5】:

          我使用bspink's way 进行了一些改进。您无需定义不想更改其顺序的字段。仅定义您想按照自己的顺序放在顶部的内容。

          (Be sure you are using the Python 3.7+)

          class SomeForm(forms.Form):
              # define only you want to put top, no need to define all of them
              # unless you need more specific ordering        
              ordered_field_names = ['planet', 'type']
          
              def __init__(self, *args, **kwargs):
                  super(SomeForm, self).__init__(*args, **kwargs)
                  # call initialization code
                  self.rearrange_field_order()
          
              def rearrange_field_order(self):
                  # add defined fields first 
                  new_fields = {field_name: self.fields.get(field_name) for field_name in self.ordered_field_names}
          
                  # then add others whose not defined in order list
                  for key, value in self.fields.items():
                      if key not in new_fields:
                          new_fields[key] = value
          
                  self.fields = new_fields
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-10-29
            • 2019-03-31
            • 2013-10-29
            • 2017-04-23
            • 2013-01-08
            • 2020-07-20
            • 2011-12-02
            • 2017-11-15
            相关资源
            最近更新 更多