2011-02-04 13 views
17

que tienen un modelo:Django: ¿Cómo hacer un formulario con plantillas personalizadas?

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

me gustaría crear un formulario que se ve algo como:

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

No estoy muy seguro de cómo hacer para hacer esto. Tal vez necesito usar 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, {})) 

Luego, en la plantilla, que me gustaría reproducir el formulario de manera diferente que por defecto. Sin embargo, no estoy muy seguro de cómo acceder a las propiedades del modelo. ¿Es este el enfoque correcto, o hay otra forma en que debería hacerlo?

Actualización: Esto es lo que estoy haciendo actualmente. Se representa exactamente como me gustaría, aparte del estilo. Sin embargo, siento que es profundamente 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 %} 

¿Hay un mejor enfoque a esto?

Además, no estoy seguro si encontraré problemas cuando se envíe el formulario o no.

Respuesta

9

No creo que necesite un formset aquí. Eche un vistazo here si desea una plantilla personalizada para una vista. Si desea crear su propia {{}} form.as_foobar, simplemente subclase forms.Form, algo como esto:

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) 

y sólo lo utilizan en su forms.py:

class ContactForm(MyForm): 
    # .. 
+0

Y ¿cómo puedo obtener los resultados de 'as_foobar' en el ¿modelo? –

+0

Además, esto especifica la salida en un nivel de campo, ¿verdad? Lo que necesito es: "Model.name.value: Model.value.value (Model.description.value)" –

+1

Debería usar {{form.as_foobar}} (similar a form.as_p) en la plantilla. Reemplace 'formulario' con lo que se llame su variable de forma. –

1

miradas como usted podría estar interesado en django-floppyforms (docs), que le da mucho más control sobre la representación de 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> 

Puede encontrar la documentación completa aquí: http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

+1

Además, no veo el punto de usar formsets. Haciendo algo de esta manera: \t de django.formas importan ModelForm \t IntegerSettingForm clase (ModelForm): \t \t clase Meta: \t \t \t modelo = IntegerSetting debe crear una clase IntegerSettingForm, que se puede utilizar para crear sus instancias forman en las vistas. – SashaN

+0

Esto imprime todos los campos, pero quiero usar el valor de un campo como etiqueta, y solo un campo realmente es una entrada. –

+0

La documentación que adjuntó fue útil, pero no mencionó un atributo de campo para imprimir el valor, no el widget. Eso es lo que realmente quiero. –

3

Para quien lo necesite la versión <table> de la respuesta de 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> 
Cuestiones relacionadas