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 以了解困难)。我认为这确实是一种对字段进行分组的好方法!
解决方案是通过访问返回的BoundFields
的field
属性的字段的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 表单字段分组的主要内容,如果未能解决你的问题,请参考以下文章