Si hemos usado Django seguro nos hemos enamorado de su forma de hacer formularios, sobre todo los que están relacionados con un modelo, puesto que son simplísimos. Hay que reconocer lo simple de Django, y gracias a esta simplicidad que no busca satisfacer completamente todas las necesidades podemos encontrarnos con situaciones que pues, no se apegan a lo que queremos hacer.
[amazon_link asins=’B009YLRYMI,B076QH5FB2,020161622X’ template=’ProductCarousel’ store=’launocom-20′ marketplace=’MX’ link_id=’98962281-912a-11e8-b0f1-a75c5f8f4964′]
Una de ellas es mostrar cierto contenido en un ChoiceField, es decir, un “SELECT”. Si nuestro formulario esta asociado a un modelo y este ChoiceField es un ForeingKey a otro modelo al momento de mostrarlo en nuestro formulario lo que hará es mostrar todo lo que hay en ese modelo.
Como hacer entonces que no se muestre todo sino solo la parte que me interesa?.
Bien, sabemos que el los campos dentro de un ModelForm
se guardan en la propiedad fields
que es básicamente un diccionario, cada campo es una llave en dicho diccionario y cada campo es en si un objeto del que después se tomara su representación HTML para imprimirla en la plantilla, pero hasta antes de la plantilla podemos cambiar parámetros. Por ejemplo, la propiedad choices
de forms.ChoiceField
.
El cambio lo podemos aplicar en el método init y podemos incluso pasar el parámetro de lo que queremos que se muestre en dicho ChoiceField
, supongamos entonces
form django import forms from models import Departamento class AddUserForm(forms.ModelForm): """Add a user""" first_name = forms.CharField(label="Nombres") last_name = forms.CharField(label="Apellidos") email = forms.EmailField(label="Correo elecrónico") username = forms.CharField(label="Nombre de usuario") password = forms.CharField(label="Contraseña") departamento = forms.ChoiceField(label="Departamento", widget=forms.widgets.Select()) def __init__(self, post=None, files=None, instance=None, departamentos=None): """Initialize the form""" # Ejecutamos Super para correr el inicializador de forms.ModelForm # Esto generará self.fields super(AddUserForm, self).__init__(post, files, instance) if departamentos: # Como en el modelo, "choices" es una tupla de tuplas # ((id, texto), (id, texto), (id, texto)) self.fields["departamento"].choices = departamentos
De esta forma estamos haciendo que el formulario, en el campo Departamento
muestre las opciones que nosotros queremos.
Así como esto, podemos hacer otras cosas, por ejemplo, borrar campos:
def __init__(self, post=None, files=None, instance=None, departamentos=None, display_username=True): """Initialize the form""" # Ejecutamos Super para correr el inicializador de forms.ModelForm # Esto generará self.fields super(AddUserForm, self).__init__(post, files, instance) if not display_username: # Removemos el campo "username" para que el usuario no lo # modifique en una edición. self.fields.pop("username")
O modificar el valor inicial de un campo:
if instance: self.fields["departamento"].initial = 3 if not instance.email: self.fields.email.initial = "email@defecto.com"