Django 表单字段分组

Posted

技术标签:

【中文标题】Django 表单字段分组【英文标题】:Django form field grouping 【发布时间】:2012-05-09 03:40:07 【问题描述】:

假设我有一个包含 20 个字段的表单,我想将其中的 10 个字段 (group1) 放在特定的 div 环境中,将其他 10 个字段 (group2) 放在不同的 div 环境中。比如:

<div class="class1">
% for field in form.group1 %
             field.label:  field 
% endfor %
</div>

<div class="class2">
% for field in form.group2 %
             field.label:  field 
% endfor %
</div>

有什么想法可以通过遍历字段来实现这一点吗?更一般地说,我希望能够使用许多不同的 div 环境和表单字段集来做到这一点。

【问题讨论】:

【参考方案1】:

任何对字段进行分组的合乎逻辑的方法都可以...假设您的表单上有一个方法可以返回您明确分组的表单字段?

为了节省打字,也许是某个字段前缀命名方案?

class MyForm(forms.Form):
    group1_field = forms.CharField()
    group1_field = forms.CharField()
    group2_field = forms.CharField()
    group2_field = forms.CharField()

   def group1(self):
        return [self[name] for name in filter(lambda x: x.startswith('group1_'), self.fields.values()]

也许在您可以过滤的字段上设置一个属性?

class MyForm(forms.Form):
    field = forms.CharField()
    field.group = 1

    field2 = forms.CharField()
    field2.group = 2

    def group1(self):
        return filter(lambda x: x.group == 1, self.fields.values())

    def group2(self):
        return filter(lambda x: x.group == 2, self.fields.values())

如果你设置了这些属性,你也可以使用 regroup 标签。

% regroup form.fields by group as field_group %
% for group in field_group %
<div class="group_ group.grouper ">
  % for field in group.list %
     field 
  % endfor %
</div>
% endfor %

【讨论】:

我喜欢使用 regroup 标签 --- 我不知道它存在。谢谢! 注意:您的第一个解决方案不能很好地循环模板中的字段 --- 使用 yield 关键字创建生成器以获取预期的字段(请参阅下面的我的帖子)并模拟 django 的典型字段迭代 我确实尝试了重组方法,但没有成功。问题是字段标签不存在新的组属性 - 但对于“field.field”标签 - 它指的是底层的python类。有没有办法通过这些基础类的属性重新组合? @Yuji'Tomita'Tomita 如果你有一个ModelForm 而不是Form,你会怎么做?在这种情况下,我们通常不会重新定义表单类中的字段。好吧,我想最简单的解决方法是放弃ModelForm 以支持Form 毕竟......对吗? 我非常喜欢您使用 regroup 模板标签的建议 - 但我无法让它发挥作用。分组form.fields 甚至form.fields.values 分别只给出键或Field 实例,而不是BoundFields。另一方面,分组forms 直接正确返回BoundFields,但是group 属性没有被转移。因此,形成一个单独的组None。有什么建议吗?【参考方案2】:

这是一个相关的 SO 问题:Django and Fieldsets on Modelform,尽管这对于我想要完成的事情来说似乎有点矫枉过正。另外,这里有一个可能的 hack,虽然我很想知道 Django 专家是如何解决这个问题的。

(0) 定义一个可迭代的 python 字段集对象,以便我们可以在 django 模板中对其进行迭代:

from django.forms.forms import BoundField

class FieldSet(object):
    def __init__(self,form,fields,legend='',cls=None):
        self.form = form
        self.legend = legend
        self.fields = fields
        self.cls = cls

    def __iter__(self):
        for name in self.fields:
            field = self.form.fields[name]
            yield BoundField(self.form, field, name)

(1) 在视图中使用:

fieldsets = (FieldSet(form_object, ('field_name1','field_name2'),
                        legend='Div env 1',
                        cls="class1"),
             FieldSet(form_object, ('field_name3','field_name4'), 
                        legend="Div env 2",
                        cls="class2"))

return render_to_response('my_form.html',
                          'form': form_object,'fieldsets':fieldsets,
                          context_instance=RequestContext(request))

(2) 现在在模板中做:

% for set in fieldsets %
    <fieldset% if set.cls % class=" set.cls "% endif %>
      <legend> set.legend </legend>
      % for field in set %
           field.label :  field 
      % endfor %
    </fieldset>
% endfor %

请注意,可以将fieldset 标记替换为div 标记来解决我的具体问题。

+++ 这个答案大部分来自this blog post by Michael Kowalchik。 +++

【讨论】:

yield self.form[name] 就足够了。 (我在导入 BoundField 时遇到了问题,但使用该行甚至没有必要。)【参考方案3】:

我终于能够将@Yuji'Tomita'Tomitas regroup-template-tag-solution 带入工作(请参阅@Yuji'Tomita'Tomitas 回答中的 cmets 以了解困难)。我认为这确实是一种对字段进行分组的好方法!

解决方案是通过访问返回的BoundFieldsfield 属性的字段的group 属性进行重组。最小的例子:

forms.py 中:

class TestForm(Form):
    a = IntegerField()
    a.group = 1
    b = IntegerField()
    b.group = 1
    c = IntegerField()
    c.group = 2
    d = IntegerField()
    d.group = 2

在模板中:

<form>
  % csrf_token %
  % regroup form by field.group as field_groups %
  % for field_group in field_groups %
    field_group.grouper
    % for field in field_group.list %
      field
    % endfor %
  % endfor %
</form>

【讨论】:

在我这边,我用它来分组我的字段:% regroup form|dictsort:"field.group" by field.group as field_groups %

以上是关于Django 表单字段分组的主要内容,如果未能解决你的问题,请参考以下文章

Django:对表单字段进行分组

Django 酥脆的表单可以与自定义小部件一起使用吗?

Django 向导表单中的条件表单字段

Laravel Nova:按列分组表单字段

Django表单,表单字段的继承和顺序

在 JSON 输出中对 Extjs 表单字段进行分组