2012-04-28 23 views
6

Powiedz, że mam formularz z 20 polami i chcę umieścić 10 z tych pól (grupa 1) w określonym środowisku div i 10 innych pól (grupa 2) w innym środowisku div. Coś jak:Zgrupowanie pól formularza 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> 

Jakieś pomysły, w jaki sposób mogę to osiągnąć, wykonując iteracje na polach? Bardziej ogólnie, chciałbym móc to zrobić z wieloma różnymi środowiskami div i zestawami pól formularzy.

Odpowiedz

13

Każda logiczna metoda grupowania pól zadziałałaby ... powiedzmy, że masz w formularzu metodę zwracającą pola formularza, które jawnie grupujesz?

Aby zapisać pisanie, być może jakiś schemat nazewnictwa pól prefiksowych?

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()] 

Być może ustawić atrybut na polu, które można filtrować według?

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()) 

Możesz także użyć znacznika przegrupowania, jeśli ustawisz te atrybuty.

{% 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

Podoba mi się użycie tagu przegrupowania --- Nie wiedziałem, że to istnieje. Dzięki! –

+0

Uwaga: twoje pierwsze rozwiązanie nie działa w pętli nad polami w szablonie --- użyj słowa kluczowego 'yield' do stworzenia generatora, aby uzyskać oczekiwane pola (zobacz mój post poniżej) i emuluj typowe iteracje pola Django –

+0

@ C.Wiesz, masz rację, zapomniałem wrócić BoundFields. Zaktualizowano. Dzięki za uwagę! –

4

Oto istotne pytanie: Django and Fieldsets on Modelform, ale wydaje się to nieco przesadzone z tego, co chcę osiągnąć. Jest jeszcze jeden możliwy hack, chociaż jestem ciekawy, jak eksperci Django rozwiązują ten problem.

(0) zdefiniować obiekt pyton fieldset że jest iterable więc możemy iteracyjne nad nim w szablonie 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) W zastosowaniu Widok:

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) teraz w szablonie zrobić:

{% 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 %} 

Należy zauważyć, że możliwe jest zastąpienie Wi fieldset tag th a div tag, aby odpowiedzieć na moje konkretne pytanie.

+++ Znaczna część tej odpowiedzi została wyodrębniona z this blog post by Michael Kowalchik. +++

+0

'yield yield self.form [name]' jest wystarczające. (Miałem problemy z importowaniem BoundField, ale z tą linią nie jest to konieczne.) – Risadinha

Powiązane problemy