2012-04-28 19 views
6

Digamos que tengo un formulario con 20 campos, y quiero poner 10 de estos campos (grupo1) en un entorno div particular y los otros 10 campos (grupo2) en un entorno div diferente. Algo como:Django agrupación de campos de formulario

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

¿Alguna idea de cómo podría lograr esto iterando sobre los campos? En términos más generales, me gustaría poder hacer esto con diferentes entornos div y conjuntos de campos de formulario.

Respuesta

13

Cualquier forma lógica de agrupar campos funcionaría ... digamos que tiene un método en su formulario que devuelve campos de formulario que agrupa explícitamente?

Para ahorrar tipeo, ¿quizás un cierto esquema de nombres de prefijo de campo?

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

¿Quizás establecer un atributo en el campo que puede filtrar?

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

También puede usar la etiqueta reagrupar si establece estos atributos.

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

Me gusta el uso de la etiqueta reagrupar --- No sabía que esto existiera. ¡Gracias! –

+0

Nota: su primera solución no funciona para recorrer los campos de la plantilla --- use la palabra clave 'yield' para crear un generador para obtener los campos esperados (vea mi publicación a continuación) y emule la iteración de campo típica de django –

+0

@ C.Reed, tienes razón, me olvidé de devolver BoundFields. Actualizado. ¡Gracias por notarlo! –

4

Aquí hay una pregunta de SO: Django and Fieldsets on Modelform, aunque esto parece un poco exagerado para lo que estoy buscando lograr. Además, he aquí un posible truco, aunque tengo curiosidad por saber cómo los expertos de Django resuelven este problema.

(0) definir un objeto pitón fieldset que es iterable por lo que podemos iterar sobre ella en una plantilla 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) En la vista de uso:

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) Ahora bien, en la plantilla de hacer:

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

en cuenta que es posible sustituir el wi fieldset etiqueta la etiqueta div para abordar mi pregunta específica.

+++ Gran parte de esta respuesta se extrae de this blog post by Michael Kowalchik. +++

+0

'yield self.form [name]' es suficiente. (Tuve problemas para importar BoundField, pero con esa línea ni siquiera es necesario). – Risadinha

Cuestiones relacionadas