widgets tutorial template form fields example bootstrap python django django-forms django-templates django-template-filters

python - tutorial - Cómo renderizar el campo de formulario django en la plantilla



django tutorial (2)

Estás haciendo que la plantilla sea demasiado complicada. Agregue una etiqueta a cada campo cuando lo cree en el método __init__ del __init__ .

for f in userlist: self.fields[str(f.id)] = forms.BooleanField(label=f.username, initial=False)

Luego simplemente recorra los campos en el formulario y ya no se preocupe por la lista de userlist .

{% for field in form %} <tr> <td>{{ field.label_tag }}</td> <td>{{ field }}</td> </tr> {% endfor %}

Quiero hacer una página con una lista de usuarios y casillas de verificación que indiquen si un usuario está seleccionado, lo que aplicará alguna acción a los usuarios seleccionados. Creé una clase de formulario que se ve así:

#in forms.py class UserSelectionForm(forms.Form): """form for selecting users""" def __init__(self, userlist, *args, **kwargs): self.custom_fields = userlist super(forms.Form, self).__init__(*args, **kwargs) for f in userlist: self.fields[str(f.id)] = forms.BooleanField(initial=False) def get_selected(self): """returns selected users""" return filter(lambda u: self.fields[str(u.id)], self.custom_fields)

En mi plantilla tengo usuarios enumerados en una tabla y quiero que la última columna de esta tabla sean esas casillas de verificación. Necesito representar campos uno por uno dependiendo de su nombre. Intenté crear una etiqueta de plantilla que devolviera el código html del elemento de formulario necesario:

#in templatetags/user_list_tags.py from django import template register = template.Library() #this is django template tag for user selection form @register.filter def user_select_field(form, userid): """ returns UserSelectionForm field for a user with userid """ key = std(userid) if key not in form.fields.keys(): print ''Key %s not found in dict'' % key return None return form.fields[key].widget.render(form, key)

Finalmente, aquí está el código de la plantilla:

<form action="" method="post"> {% csrf_token %} <table class="listtable"> <tr> <th>Username</th> <th>Select</th> </tr> {% for u in userlist %} <tr> <td>{{u.username}}</td> <td>{{select_form|user_select_field:u.id}}</td> </tr> {% endfor %} </table> <p><input type="submit" value="make actions" /></p>

Sin embargo, esto no vincula esos widgets al formulario y, por lo tanto, después de enviar el formulario, la validación falla. El mensaje de error dice que todos los campos personalizados son obligatorios. Asi que aqui están mis preguntas:

  1. ¿Cuál es la forma correcta de representar campos de formularios separados?

  2. ¿Cuál es la forma correcta de crear un formulario de este tipo con casillas de verificación? (Quiero decir, tal vez mi método es estúpido y hay una manera mucho más fácil de lograr lo que quiero.


Ok, creo que he encontrado una forma de representar correctamente los campos de formulario separados. Lo encontré viendo fuentes django. Django.forms.forms.BaseForm clase Django.forms.forms.BaseForm tiene el método _html_output que crea una instancia de Django.forms.forms.BoundField y luego agrega unicode(boundField) a la salida html. Hice exactamente lo mismo y funcionó perfectamente:

#in templatetags/user_list_tags.py from django import template from django import forms register = template.Library() #this is djangp template tag for user selection form @register.filter def user_select_field(form, userid): """ returns UserSelectionForm field for a user with userid """ key = str(userid) if key not in form.fields.keys(): print ''Key %s not found in dict'' % key return None #here i use BoundField: boundField = forms.forms.BoundField(form, form.fields[key], key) return unicode(boundField)

Eso generó el mismo html que {{form.as_p}}, por lo que la solicitud POST se verá exactamente igual y el formulario se procesará correctamente.

También solucioné algunos errores en mi clase de formulario:

#in UserSelectionForm definition: ... #__init__ for f in userlist: self.fields[str(f.id)] = forms.BooleanField(initial=False, required=False) #get_selected return filter(lambda u: self.cleaned_data[str(u.id)], self.custom_fields)

Eso ahora parece funcionar como lo planeé, sin ningún javascript.