Curso Django: Los formularios
Los formularios permiten el ingreso de datos para su procesamiento, ya sea para crear nuevos contenidos, para modificar el contenido que ya esta registrado previamente y hasta para realizar búsquedas.
Django posee una interfaz administrativa que hemos estado utilizando hasta el momento en lo que va del curso, pero cuando nos encontramos en la posición de elaborar interfaces de entrada o edición de datos, para los usuarios de nuestra aplicación, en algunas circunstancias, darles acceso al administrador de Django resulta contraproducente.
Es por ello que resulta mejor preparar nuestros formularios para manejar estas circunstancias, entre otras ocasiones.
Para entender mejor lo que Django permite, veamos esta lista de ‘superpoderes’ de Django:
- Mostrar un formulario HTML generado a partir de reglas básicas.
- Generar formularios HTML validados a partir de modelos ya declarados.
- Validar la información que se desea registrar a través del formulario.
- Mostrar nuevamente el formulario, haciendo notar los errores que ha producido la validación.
- Convertir la información subida en tipos de datos de Python, para procesarlos de acuerdo a las vistas.
Para nuestro ejemplo de la semana, usaremos tres formularios, dos de ellos generados a partir de modelos y uno sin relación a algún modelo, pero con la capacidad de procesar la información y enviar un correo electrónico, utilizando gmail.
Nota: El archivo forms.py
Creamos nuestro archivo forms.py y en las primeras líneas ponemos:
Estas líneas permitirán usar los elementos ya construidos (ModelForm para usar los modelos ya declarados, forms para declarar nuevas reglas para un formulario y los modelos de nuestra aplicación principal)
Hoja de Trucos
Como se ha estado haciendo costumbre, esta semana también tenemos una chuleta (cheatsheet) para el manejo de formularios con Django, esta contiene los campos que vienen ya construidos, los atributos y las opciones de validación.
Con esta referencia en mano empezamos a crear nuestros formularios.
Objetos Formulario
Un objeto formulario en Django es una secuencia de campos y reglas de validación, que permiten depurar la información requerida y procesarla eficientemente. Estos campos y reglas deben ser declarados en el orden que se desea que aparezcan. Las clases formulario son creadas como subclases de django.forms.Form y tienen un estilo de declaración muy similar a los modelos de Django.
Para nuestro ejemplo consideraremos implementar un formulario de contacto, que tendrá solo dos campos: un correo electrónico y un mensaje, debe lucir así:
Este Formulario, debe ir de la mano de una vista que permita procesar los datos que reciba, esta vista será declarada en views.py, primero debemos modificar nuestras primeras líneas para importar todo lo necesario, luego declarar una nueva vista.
En donde encontramos: [email protected], debe ser reemplazado por el email que recibirá el mensaje. Para que funcione el envio del mensaje al correo electrónico debemos, agregar al final de nuestro archivo settings.py, las siguientes configuraciones:
En donde encontramos: [email protected], debe ser reemplazado por la cuenta que enviará el mensaje (debe ser una cuenta válida en gmail). Necesitamos también una plantilla, en este caso se llamara: contacto.html
Para que nuestra aplicación sea navegable, modificamos base.html, para que quede con el siguiente menú:
También es necesaria una URL que convoque a esta vista por lo tanto debemos agregar la siguiente línea dentro de nuestra configuración en urls.py:
url(r'^contacto/$','principal.views.contacto'),
Formularios a partir de Modelos
Si se esta construyendo una aplicación que gestiona una base de datos, lo más apropiado es usar los modelos ya declarados como formularios, y así evitar estar repitiendo las mismas reglas para procesar los datos.
Por esta razon, Django provee una clase de ayuda que permite crear un formulario a partir de un modelo, esta clase se llama ModelForm, y se emplea así (forms.py):
Las vistas para manejar estos formularios serían estas:
Notar que se usa HttpResponseRedirect para redireccionar a una URL. Las plantillas recetaform.html y comentarioform.html serían estas:
Y tendríamos que modificar recetas.html para agregar un enlace para la creación de nuevas recetas
<a href="/receta/nueva">Agregar una receta</a>
La configuración para la URL esta:
url(r'^receta/nueva/$','principal.views.nueva_receta'), url(r'^comenta/$','principal.views.nuevo_comentario'),
Resultado final
Los archivos: forms.py, views.py, urls.py y base.html quedán de la siguiente manera:
Y debemos tener las siguientes interfaces, como resultado:
Documentación oficial de Django
La mejor forma de enterarse todo lo que puede hacer Django, es revisando su documentación, para el caso de formularios tiene: La API de formularios, Campos de formulario, Validación de campos y formularios, Formularios múltiples, Archivos para procesar Formularios, Asistente para formularios, entre otras cosas más. Si deseas ir mas alla con los formularios, pues este es tu punto de partida.
Repositorio del proyecto y video complementario
Si te perdiste de algún detalle, o deseas ver como va quedando el código oficial de nuestro proyecto de ejemplo, no te olvides que siempre puedes revisar el repositorio del proyecto en github.
Por otro lado este video nos da mayores referencias del procesamiento de formularios con Django.
[youtube http://www.youtube.com/watch?v=Wh9a0obtQUQ]
La próxima semana: Archivos Estáticos
La próxima semana se viene un capítulo interesante sobre los archivos estáticos dentro de nuestro proyecto, los mas comunes son archivos CSS, JavaScript o imágenes que pertenezcan a la interfaz de nuestra aplicación. Veremos como agregarlos y ya podremos usar cualquier framework frontend para construir rápidamente nuestra interfaz.
No se olviden prácticar con proyectos propios, probar cosas diferentes al ejemplo, escribir código (no se aprende copiando y pegando), revisar la documentación, dejar sus comentarios que enriquecen increiblemente el curso, difundirlo a los que aún no conocen Django, twittear sobre el curso y todo lo que ustedes vienen haciendo con el curso.
Que tengan un buen inicio de semana :). Happy coding!
Como dicen en España: “La leche tío, eres la leche…” uno de los mas complicados temas en los frameworks son el uso de formularios y eso debido a que no están muy bien ejemplificados, pero este post se merece un 10. Gracias por el esfuerzo realizado para llevarnos un nuevo tema casa semana.
@zerohours
muy bueno. impresionado de que con Django sin escribir tanto código realizas muchas funcionalidades
Django es super genial :3
excelente continuo leyendo los capítulos todos los lunes
Genial tutorial, creo que ya es hora de realizar un proyecto completo para practicar como se debe
Excelente colección de tutoriales, muy claros y específicos. Y las cheatsheets no tienen precio. ¡Gracias por compartir con nosotros todo esto!
Oh my god CSS yeah :3
Muchas gracias Brizuela por seguir el curso 😀 y que bueno que te sea de utilidad
Al final del curso los juntare todos para que tenga un documento muy completo.
Gracias a todos por sus comentarios, es un agrado que les guste
Hola.
Aquí pueden encontrar los slides del video que recomienda @neosergio.
http://yergler.net/2012/pycon-forms/
Por favor, muy bueno el curso, cuando continúa?????
Realmente muy bueno, y sencillo. Despues del curso, cuando me haga mas tiempo, a leer la docu oficial 😉
Hola gente, muy bueno el tuto, una consulta, alguien probo subir a algun servidor? resultados? hay que realizar muchos cambios sobre lo que dice el tutorial para subir a google app engine?
@neosergio en el curso si vamos a hablar de la gestión de usuario???
El proximo lunes Yohani
El ultimo capitulo hablará sobre ello
Dentro de 2 lunes
Sergio espero realmente que siga este curso… muy completo :’) …. hace poco entre en esto de python y lo que mas me llama la tencion es la programacion web que mejor que aprender un framework que ayuda tanto… Muchas gracias
Huy que buenos tutoriales, gracias @neosergio, empece con Django apenas esta semana y ya me siento muy familiarizado. tienes una buena didáctica.
Una pregunta: Se pueden pasar variables desde y hacia javascript de manera similar a como se hace en las plantillas {% variable %}
Si no me equivoco Diego, Django tienes tus secciones osea que esta separado, tu css, js, etc !! estos los llamadas a tu plantillas para luego usarlos ! se pueden usar mediante tags, propios de django o con codigo html !! depende de como quieras llevar y si de si es extenso ! pero si se puede llamar a un javascript ! bajo los terminos de Django
Sergio en el primer ejemplo de formulario, en la vista tenemos 2 if y un else, o sea que deberian haber tres return para las tres alternativas, pero solo hay 2 return. Me lanza un error que dice que falta un HttpResponse…
The view principal.views.contacto didn’t return an HttpResponse object.
No esta faltando un return?
Hola sergio en el cheatsheet que dejo hay opciones de RadioSelect y CheckboxInput, e intentado implementarlos y no me salen.
Por ejemplo para RadioSelect, lo que hice es hacer un choice:
sexo_choice = ((0,’Varon’),(1,’Mujer’),)
y lo llame asi:
sexo = ChoiceField(widget=RadioSelect, choices=SEXO_CHOICES)
Pero cuando lo muestro en la vista me aparece un tipo select y no inputs como dice la documentacion.
Y pues CheckboxInput no se como se implementa
Matias, yo lo tengo con dos return y no tengo problemas, verifica que estes importanto HttpResponse. Saludos.
Ya solucione mi problema. Habia puesto mal la identacion del else, lo puse para el segundo if.
Una pregunta, ¿el formulario de contacto debería de funcionar? ¿O como estoy trabajando en local no funciona? Es que al rellenar los datos en el formulario y darle a enviar me devuelve un error.
¡Saludos y gracias!
Mientras tengas internet deberia funcionar porque trabaja con el servidor de correo de Gmail y no con un servidor local. Postea el error que te arroja.
Fantástico el material del tema, pero como hago un formulario para editar una receta??
Como elimino una receta
Podrías revisar este enlace, te será de mucha ayuda para incluir Javascript (http://www.dajaxproject.com/)
En la documentación muestra que el ChoiceField devuelve un select (https://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.ChoiceField) y para el Checkbox puedes usar un tipo Boolean como muestra aquí (https://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.BooleanField)
Que bueno, no te olvides revisar el código del proyecto en Github para comparar tus resultados (http://neosergio.github.com/recetario_mdw/)
Funciona con el smtp de gmail, revisa tus datos de autenticación. También dale una vista al código del proyecto para comparar si todo va bien (http://neosergio.github.com/recetario_mdw/)
Se puede usar el parámetro ‘instance’. Fijate la última línea de este ejemplo (https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#modelform) form = ArticleForm(instance=article)
En tu vista puedes usar ‘delete’, fijate este ejemplo: https://docs.djangoproject.com/en/dev/topics/db/queries/#deleting-objects
[…] Curso Django: Los formularios […]
Que buena información estas aportando Sergio, Que bueno que hayan personas que no sean mezquinas con su conocimiento.
Gracias.
PD: Ya logre modificar y eliminar recetas =)
Hola a todos.
Increíble curso. Lo estoy siguiendo hace un par de semanas. No tenia conocimientos de python y nada de programación web. Ahora me estoy enamorando tanto de python como django.
Pero tan novato soy que me he estancado. He comparado el codigo github con el mio y soy incapaz de ver cual es el problema que tengo.
Cuando ejecuto el codigo de github la aplicacion me funciona a las mil maravillas, en la mia los formularios no me van y no se por que.
Os adjunto el error que me devuelve:
AttributeError at /comenta/
‘WSGIRequest’ object has no attribute ‘methodo’
Request Method: GET
Request URL: http://localhost:8000/comenta/
Django Version: 1.4.1
Exception Type: AttributeError
Exception Value:
‘WSGIRequest’ object has no attribute ‘methodo’
Exception Location: D:\proyectos\python\recetario\principal\views.py in nuevo_comentario, line 56
Python Executable: C:\Python27\python.exe
Python Version: 2.7.3
Python Path:
[‘D:\\proyectos\\python\\recetario’,
‘C:\\Python27\\lib\\site-packages\\setuptools-0.6c11-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\twill-0.9-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\bottle-0.10.11-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\authkit-0.4.5-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\webob-1.2.2-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\decorator-3.3.3-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\elementtree-1.2.7_20070827_preview-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\python_openid-2.2.5-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\pastescript-1.7.5-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\beaker-1.6.4-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\pastedeploy-1.5.0-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\nose-1.1.2-py2.7.egg’,
‘C:\\Python27\\lib\\site-packages\\paste-1.7.5.1-py2.7.egg’,
‘C:\\Windows\\system32\\python27.zip’,
‘C:\\Python27\\DLLs’,
‘C:\\Python27\\lib’,
‘C:\\Python27\\lib\\plat-win’,
‘C:\\Python27\\lib\\lib-tk’,
‘C:\\Python27’,
‘C:\\Python27\\lib\\site-packages’,
‘C:\\Python27\\lib\\site-packages\\PIL’]
Server time: dom, 2 Sep 2012 11:38:50 +0200
Gracias.
Excelente curso..
Tengo una duda/problema que no eh podido solucionar si por ejemplo en mi comentario quiero que tenga:
Subject / Name / Comment
y el Subject por default sea = al nombre de la receta donde esta comentado .. me pueden explicar como hacer eso. ya busque e intente algunas burradas pero no me salio.
Buenas con todos, una duda si la cuenta de gmail que configuras en settings.py tienes activada la verificación en 2 pasos, que se puede hacer para que funcione. Intente con otra cuenta que no tiene activada esa función y me funciono normal.
Saludos
sergio, he estado aprendiendo un poco de python con este curso que por cierto es espectacular, hey aprendido python y django en muy poco tiempo pero los formularios son lo unico que no logro hacer por mas que trato y trato de lo cual me gustaria que me ayudaras, como me podria comunicar contigo? muchas gracias, ojala pudieras hacer uno mas avanazado o de on rails para windows.
Buen Dia,
Excelente curso estoy desarrollando una aplicacion que permita tomar pruebas vocacionales, en medio de todo al seguir los pasos me genero el siguiente error.
ValueError at /contactenos/
The view encuestas.views.contacto didn’t return an HttpResponse object.
Request Method: GET
Request URL: http://localhost:8000/contactenos/
Django Version: 1.4
Exception Type: ValueError
Exception Value:
The view encuestas.views.contacto didn’t return an HttpResponse object.
Exception Location: C:\Python27\lib\site-packages\django\core\handlers\base.py in get_response, line 129
Python Executable: C:\Python27\python.exe
Python Version: 2.7.3
Python Path:
[‘C:\\Users\\DGo\\My Documents\\Aptana Studio 3 Workspace\\sursall\\sursall’,
‘C:\\Users\\DGo\\AppData\\Local\\Aptana Studio 3\\plugins\\org.python.pydev_2.2.1.2011073123\\PySrc’,
‘C:\\Windows\\system32\\python27.zip’,
‘C:\\Python27\\DLLs’,
‘C:\\Python27\\lib’,
‘C:\\Python27\\lib\\plat-win’,
‘C:\\Python27\\lib\\lib-tk’,
‘C:\\Python27’,
‘C:\\Python27\\lib\\site-packages’]
Server time: Mon, 15 Oct 2012 18:48:22 -0500
Agradezco su ayuda…
Hola a todos!
Tengo una pregunta, si quieres crear un formulario de un modelo en el que quieres guardar una referencia al usuario que lo ha creado (relación una a muchos) a parte de otros campos como lo haces?
Por ejemplo, quiero que el usuario pueda subir un track y en el modelo Track se guarde el usuario que lo ha subido a parte de la dirección donde se enquentra el archivo.
Excelente curso! Me está ayudando mucho!!
@neosergio muy bueno. impresionante, Pero como hago para realizar una consulta a la base de dato(modelo) usando el formulario, es decir quiero buscar una receta ‘especifica’ en la base de dato de una gran cantidad ??
————————————————————————————————–
tengo mi modelo y mi formulario creado y se que para obtener los resultados especifico utilizo
receta = Receta.objects.filter()
—————————————————————————————————
funciona cuando uso una contaste:
receta = Receta.objects.filter(titulo=’piña colada’)
—————————————————————————————————-
pero no funciona cuando uso una variable que es igual a la clase del formulario:
receta = Receta.objects.filter(titulo=formulario)
Buenas tardes Sergio, llevo unas semanas siguiendo tu curso para Django y mi opinión personal, en relación al curso, es bastante buena y positiva. En primer lugar no se si debo formularte esta cuestión a través de este medio, debo hacerlo de otra forma o simplemente no puedo contactor contigo.
Intentaré explicarte mi sensación: cuando empezamos el curso dimos de alta los modelos, configuraciones básicas, y activamos la interfaz administrativa, era todo fantástico y sobre todo el aspecto de la interfaz, parecia que estaba todo pensado y yo simplemente debía aprender Django para moldearlo a mis necesidades. A medida que avanza el curso me doy cuenta, quizás por mi poca experiencia y conocimientos, que no era así. Que la interfaz administrativa era un tema y las interfaz para los usuarios es otro, es aquí cuando me vengo abajo, y sobre todo cuando veo que las dos interfaces no tienen nada que ver una con otra. Mi pregunta es, se debe o puedo modificar la interfaz administrativa para que tenga el mismo aspecto pero la utilicen los usuarios.
No se si me he expresado bien, te agradezco tu atención de antemano y espero tus comentarios.
Un saludo Fran