2009-02-06 22 views
34

So che è possibile specificare i set di campi in django per gli Admin helper. Tuttavia, non riesco a trovare nulla di utile per ModelForms. Solo alcune patch che non posso usare. Mi sto perdendo qualcosa? C'è un modo per ottenere qualcosa di simile ai fieldets senza scrivere manualmente ogni campo sul mio template nel tag appropriato.Django e fieldset su ModelForm

Mi piacerebbe idealmente iterare attraverso un set di BoundFields. Tuttavia, fare qualcosa di simile alla fine del mio 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 

fallisce come gli elementi contenuti nella mia struttura dati sono i campi prime, non i BoundFields. Sembra che BoundFields sia generato al volo ... questo mi rende triste. Potrei creare la mia sottoclasse di form. Form che contiene un concetto di set di campi (anche uno approssimativo che non è compatibile con le versioni precedenti ... questo è solo per il mio progetto) e, in tal caso, puoi dare un puntatore? Non voglio scherzare con il codice django.

risposta

34

I set di campi in modelform sono ancora in fase di "progettazione". C'è uno ticket in Django trac con bassa attività.

E 'qualcosa che mi sono interessato nella ricerca me stesso in un prossimo futuro, ma dal momento che non ho ancora fatto il meglio che posso offrire sono questi frammenti:

Edit: ho appena notato di nuovo questa domanda e mi ri Alize necessita di una modifica per indicare il progetto di Carl django-form-utils che contiene una classe BetterForm che può contenere campi. Se ti piace questo progetto dargli un +1 per la sua risposta qui sotto :)

+1

Il secondo link mi ha dato l'idea che avevo bisogno di realizzare il mio rudimentale supporto fieldset. Grazie. –

+1

Nov. 2010, utilizzato correttamente django-form-util con 1.2.3. Grazie per il suggerimento. – Boldewyn

16

Una cosa che puoi fare è spezzare i tuoi fieldset logici in classi di moduli separati.

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

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

loro Passare al modello in diverse variabili e rompere le formsets:

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

In questo senso ciascuna delle proprie classi di form è solo un frammento del modulo HTML vero e proprio.

Introduce un tocco di complessità quando si chiama Salva nel modulo. Probabilmente vorrai passare commit = False e quindi unire gli oggetti risultanti. O semplicemente evita di utilizzare ModelForm.save del tutto e compila a mano il tuo oggetto modello con 'clean_data'

+1

Questo è troppo difficile, specialmente nel livello vista. – Greg

+3

@Greg, Il downvote non mi infastidisce, ma il tuo commento è confuso. Cosa intendi con troppa fatica? Rompere una forma monolitica in frammenti di forma separati che puoi manipolare indipendentemente l'uno dall'altro è un approccio idiomatico a questo problema. Django potrebbe aver aggiunto più utilità "fieldset" nei due anni da quando ho fornito questa risposta, ma l'approccio è comunque valido. –

+1

Il punto di vista di Greg è terribile invalido! .. Questa opzione è applicabile e flessibile. L'unica volta in cui non funzionava, era quando nel metodo 'clean' potevano essere necessari alcuni dati da due o più campi di forma! – StefanNch

50

Penso che this snippet faccia esattamente quello che vuoi. Ti offre una sottoclasse di Form che ti consente di suddividere in modo dichiarativo il tuo modulo in campi e di scorrere iterate nel tuo modello.

Update: Questo frammento da allora è diventata parte della django-form-utils

+0

Eccellente, sta andando nel mio attuale progetto! –

+0

Grazie per django-form-utils! Funziona come un fascino. – Boldewyn

+0

Uso anche form-utils e ho anche scritto un'estensione per form-utils che consente di disporre i campi in righe all'interno del fieldset .. proprio come admin. Sto pianificando di contattare l'autore di form-utils per vedere se lo accetterà come patch. Nel frattempo, se ti piacerebbe, basta chiedere ... –

0

Questo è il codice che ho sviluppato per comprendere tag personalizzati (con collegamenti). L'ho applicato per creare un fieldset.

Disclaimer: Io incoraggio l'uso di una qualsiasi delle risposte di cui sopra, questo era solo per motivi di apprendimento.

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>