2011-02-04 14 views
17

Ho un modello:Django: come creare un modulo con template personalizzati?

class Setting(models.Model): 

    class Meta: 
     abstract = True 

    name = models.CharField(max_length=120, primary_key=True) 
    description = models.CharField(max_length=300, blank=True) 

class IntegerSetting(Setting): 
    value = models.IntegerField() 

Vorrei creare un modulo che sembra qualcosa di simile:

<form method="POST" action=""> 
    {% for model in models %} 
    <label>{{model.name}}</label> <input value='{{model.value}}' /> 
    <p>{{model.description}}</p> 
    {% endfor %} 
</form> 

io non sono del tutto sicuro di come andare a fare questo. Forse ho bisogno di usare un formset?

from django.forms.models import modelformset_factory 
from apps.about.models import Setting, IntegerSetting 

def site_settings(request): 
    formset = modelformset_factory(IntegerSetting)() 

    return render_to_response("about/admin/site-settings.html", {'formset': formset}, RequestContext(request, {})) 

Quindi nel modello, vorrei rendere il modulo in modo diverso rispetto al valore predefinito. Non sono abbastanza sicuro di come accedere all'accesso alle proprietà del modello, comunque. È questo l'approccio giusto, o c'è un altro modo in cui dovrei fare per farlo?

Aggiornamento: questo è ciò che sto facendo attualmente. Rende esattamente come mi piacerebbe, a parte lo stile. Tuttavia, ritengo che sia profondamente hacky:

class SettingsForm(ModelForm): 
    class Meta: 
     model = IntegerSetting 

    def as_table(self): 
     bound_field = BoundField(self, self.fields['value'], 'value') 
     return mark_safe("<tr><td><label>%s</label></td><td>%s\n<p class='help'>%s</p></td></tr>" % (self.instance.name, 
                     self.instance.description, 
                     bound_field.__unicode__())) 

def edit_settings(request): 
    forms = [SettingsForm(instance=intSetting) for intSetting in IntegerSetting.objects.all()] 

    return render_to_response("admin/edit-settings.html", {'forms': forms}, RequestContext(request, {})) 

edit-settings.html:

{% extends "admin/base_site.html" %} 
{% block title %}System Settings{% endblock %} 

{% block content %} 
    <form method="post" action=""> 
     <table> 
     {% for form in forms %} 
     {{form}} 
     {% endfor %} 
     </table> 
    </form> 
{% endblock %} 

C'è un approccio migliore a questo?

Inoltre, non sono sicuro se incontrerò problemi quando il modulo viene inviato o meno.

risposta

9

Non penso che sia necessario un formset qui. Dai un'occhiata a here se vuoi un modello personalizzato per una vista. Se si desidera creare il proprio {{}} form.as_foobar, solo sottoclasse FORMATI.FORM, qualcosa di simile:

class MyForm(forms.Form): 
    def as_foobar(self): 
    return self._html_output(
     normal_row = u'%(label)s %(field)s%(help_text)s', 
     error_row = u'%s', 
     row_ender = '', 
     help_text_html = u' %s', 
     errors_on_separate_row = False) 

e basta usare nel vostro forms.py:

class ContactForm(MyForm): 
    # .. 
+0

E come avrei ottenuto i risultati del 'as_foobar' nel modello? –

+0

Inoltre, questo sta specificando l'output a livello di campo, giusto? Quello di cui ho bisogno è: "Model.name.value: Model.value.value (Model.description.value)" –

+1

Userai {{form.as_foobar}} (simile a form.as_p) nel modello. Sostituisci "modulo" con qualunque sia la tua variabile di forma chiamata. –

1

Looks come potresti essere interessato a django-floppyforms (docs), che ti dà un maggiore controllo sul rendering del campo.

18
<form action="/contact/" method="post"> 
    {% for field in form %} 
     <div class="fieldWrapper"> 
      {{ field.errors }} 
      {{ field.label_tag }}: {{ field }} 
     </div> 
    {% endfor %} 
    <p><input type="submit" value="Send message" /></p> 
</form> 

È possibile trovare la documentazione completa qui: http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

+1

Inoltre non vedo al punto di usare i formset. Fare qualcosa in questo modo: \t da django.forme importare ModelForm \t classe IntegerSettingForm (ModelForm): \t \t classe Meta: \t \t \t modello = IntegerSetting dovrebbe creare una classe IntegerSettingForm, che è possibile utilizzare per creare le istanze di forma in vista. – SashaN

+0

Stampa tutti i campi, ma voglio usare il valore di un campo come etichetta e solo un campo è effettivamente un input. –

+0

La documentazione allegata era utile, ma non menzionava un attributo campo per stampare il valore, non il widget. Questo è quello che voglio veramente. –

3

Per chi ha bisogno la versione <table> della risposta di jbcurtin:

<form method="post">{% csrf_token %} 
    <table> 
    {% for field in form %} 
     <tr> 
     <th>{{field.label_tag}}</th> 
     <td> 
      {{ field.errors }} 
      {{ field }} 
     </td> 
     </tr> 
    {% endfor %} 
    </table> 
    <hr/> 
    <input type="submit" value="Conferma" /> 
</form> 
Problemi correlati