2009-02-06 28 views
34

Sé que puede especificar conjuntos de campo en django para los ayudantes de administración. Sin embargo, no puedo encontrar nada útil para ModelForms. Solo algunos parches que no puedo usar. ¿Me estoy perdiendo de algo? ¿Hay alguna manera de lograr algo así como conjuntos de campos sin escribir manualmente cada campo en mi plantilla en la etiqueta correspondiente?Django y fieldsets en ModelForm

Me gustaría iterar idealmente a través de un conjunto de BoundFields. Sin embargo, hacer algo como esto al final de mi ModelForm:

fieldsets = [] 
    fieldsets.append(('Personal Information', 
         [username,password,password2,first_name,last_name,email]),) # add a 2 element tuple of string and list of fields 
    fieldsets.append(('Terms & Conditions', 
         [acceptterms,acceptprivacy]),) # add a 2 element tuple of string and list of fields 

falla como los elementos contenidos en mi estructura de datos son los campos primas, no los BoundFields. Parece que BoundFields se genera sobre la marcha ... esto me entristece. ¿Podría crear mi propia subclase de formularios.Forma que contiene un concepto de conjuntos de campo (incluso uno áspero que no es compatible con versiones anteriores ... esto es solo para mi propio proyecto) y si es así, ¿puede dar cualquier puntero? No quiero meterme con el código django.

Respuesta

34

Los conjuntos de campos en formas de modelo todavía están en etapa de "diseño". Hay un ticket en el tracto Django con poca actividad.

Es algo que he estado interesado en la investigación a mí mismo en un futuro próximo, pero ya que no lo he hecho todavía lo mejor que puedo ofrecer son estos fragmentos:

Editar: me acabo de notar esta pregunta de nuevo y me re Alize necesita una edición para señalar el proyecto de Carl django-form-utils que contiene una clase de BetterForm que puede contener conjuntos de campo. Si te gusta este proyecto, dale un +1 por su respuesta a continuación :)

+1

El segundo enlace me dio la idea de que tenía que poner en práctica mi apoyo conjunto de campos rudimentaria. Gracias. –

+1

nov. 2010, usó django-form-utils con éxito con 1.2.3. Gracias por la pista. – Boldewyn

16

Una cosa que puedes hacer es romper tus conjuntos de campos lógicos en clases de formulario de modelo separadas.

class PersonalInfoForm (forms.ModelForm): 
    class Meta: 
     model=MyModel 
     fields=('field1', 'field2', ...) 

class TermsForm (forms.ModelForm): 
    class Meta: 
     model=MyModel 
     fields=('fieldX', 'fieldY', ...) 

pasarlos a la plantilla en diferentes variables y romper los juegos de formularios:

<form ...> 
    <fieldset><legend>Personal Information</legend> 
     {{ personal_info_form }} 
    </fieldset> 
    <fieldset><legend>Terms and Conditions</legend> 
     {{ terms_form }} 
    </fieldset> 
</form> 

En ese sentido cada una de sus clases de formulario es sólo un fragmento del formulario HTML real.

Introduce un toque de complejidad cuando llamas guardar en el formulario. Probablemente quiera pasar commit = False y luego fusionar los objetos resultantes. O simplemente evite usar ModelForm.save por completo y llene su objeto de modelo a mano con 'cleaned_data'

+1

Esto es demasiado esfuerzo, especialmente en la capa de vista. – Greg

+3

@Greg, el voto a favor no me molesta, pero su comentario es confuso. ¿Qué quieres decir con demasiado esfuerzo? Romper una forma monolítica en fragmentos de formas separadas que puedes manipular de forma independiente uno del otro es un enfoque idiomático a este problema. Django puede haber agregado más utilidades de campo en los dos años desde que proporcioné esta respuesta, pero el enfoque sigue siendo válido. –

+1

¡El punto de vista de Greg es terriblemente inválido! ... Esta opción es aplicable y flexible. La única vez que no funcionó fue cuando en el método "limpio" algunos datos de dos o más conjuntos de campos de formulario pueden ser necesarios. – StefanNch

50

Creo que this snippet hace exactamente lo que quiere. Le da una subclase de formulario que le permite subdividir declarativamente su formulario en conjuntos de campo e iterar a través de ellos en su plantilla.

Actualización: Este recorte tiene ya a formar parte de django-form-utils

+0

¡Excelente, va en mi proyecto actual! –

+0

¡Gracias por django-form-utils! Funciona de maravilla. – Boldewyn

+0

Estoy usando form-utils también, y también he escrito una extensión para form-utils que permite que los campos se organicen en filas dentro del fieldset ... al igual que admin. Estoy planeando contactar al autor de form-utils para ver si lo va a aceptar como un parche. Mientras tanto, si te gustaría, solo pregunta ... –

0

Este fue el código que desarrollé para comprender las etiquetas personalizadas (con enlaces). Lo apliqué para crear un fieldset.

Descargo de responsabilidad: Recomiendo el uso de cualquiera de las respuestas anteriores, esto solo por el simple hecho de aprender.

templatetags/myextras.py:

from django import template 
from django.template import Context 

register = template.Library() 


class FieldsetNode(template.Node): 
    """ Fieldset renderer for 'fieldset' tag """ 
    def __init__(self, nodelist, fieldset_name): 
     """ Initialize renderer class 
     https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-renderer 
     :param nodelist: a list of the template nodes inside a block of 'fieldset' 
     :param fieldset_name: the name of the fieldset 
     :return: None 
     """ 
     self.nodelist = nodelist 
     self.fieldset_name = fieldset_name 

    def render(self, context): 
     """ Render the inside of a fieldset block based on template file 
     https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#auto-escaping-considerations 
     :param context: the previous template context 
     :return: HTML string 
     """ 
     t = context.template.engine.get_template('myapp/fieldset.html') 
     return t.render(Context({ 
      'var': self.nodelist.render(context), 
      'name': self.fieldset_name, 
     }, autoescape=context.autoescape)) 


@register.tag 
def fieldset(parser, token): 
    """ Compilation function for fieldset block tag 
    Render a form fieldset 
    https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#writing-the-compilation-function 
    https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/#parsing-until-another-block-tag 
    :param parser: template parser 
    :param token: tag name and variables 
    :return: HTML string 
    """ 
    try: 
     tag_name, fieldset_name = token.split_contents() 
    except ValueError: 
     raise template.TemplateSyntaxError("%r tag requires a single argument" % token.contents.split()[0]) 
    if not (fieldset_name[0] == fieldset_name[-1] and fieldset_name[0] in ('"', "'")): 
     raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name) 
    nodelist = parser.parse(('endfieldset',)) 
    parser.delete_first_token() 
    return FieldsetNode(nodelist, fieldset_name[1:-1]) 

templates/myapp/fieldset.html:

<div class="fieldset panel panel-default"> 
    <div class="panel-heading">{{ name }}</div> 
    <div class="panel-body">{{ var }}</div> 
</div> 

templates/myapp/myform.html:

<form action="{% url 'myapp:myurl' %}" method="post"> 
    {% csrf_token %} 
    {% fieldset 'General' %} 
     {{form.myfield1 }} 
    {% endfieldset %} 
    {# my submit button #} 
</form> 
Cuestiones relacionadas