2012-04-28 95 views
6

假設我有一個包含20個字段的表單,並且我希望將這些字段中的10個(group1)放在特定的div環境中,而其他10個字段(group2)放在不同的div環境中。例如:Django表單字段分組

<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環境和一組表單域來實現這一點。

回答

13

將字段分組的任何邏輯方法都可以工作......假設您的窗體上有一個方法返回您明確分組的窗體字段?

爲了節省打字的時間,可能是某個字段的前綴命名方案?

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 %} 
+0

我喜歡使用重新分組標記---我不知道它存在。謝謝! – 2012-04-28 21:45:30

+0

注意:你的第一個解決方案不太適合循環模板中的字段---使用yield關鍵字來創建一個生成器以獲得預期的字段(參見下面的文章)並模擬django的典型字段迭代 – 2012-04-28 22:49:54

+0

@ C.Reed,你是對的我忘了返回BoundFields。更新。感謝您的注意! – 2012-04-28 23:30:14

4

下面是一個相關的SO問題:Django and Fieldsets on Modelform,雖然這看起來有點矯枉過正,我期待完成。此外,這裏有一個可能的黑客攻擊,儘管我很好奇聽到Django專家如何解決這個問題。

(0)定​​義蟒字段集對象,它是可迭代,所以我們可以在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標籤的Wi th div標籤來解決我的具體問題。

+++這個答案很多都是從this blog post by Michael Kowalchik中提取的。 +++

+0

'yield self.form [name]'就足夠了。 (我在導入BoundField時遇到了問題,但使用該行甚至沒有必要。) – Risadinha 2015-10-13 15:19:32