Curso Django

El web framework para perfeccionistas

Desarrollo rápido y limpio basado en Python

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

Para crear formularios se usa por convención un archivo nuevo llamado: forms.py que se ubicará en la carpeta de la aplicación, esa misma donde se encuentran los archivos: models.py y views.py. Sin embargo esto no es obligatorio, pueden crearse también en el archivo models.py

Creamos nuestro archivo forms.py y en las primeras líneas ponemos:

forms.py import

forms.py import

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.

Django Cheatsheet Forms

Django Cheatsheet Forms

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í:

ContactoForm

ContactoForm

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.

views.py import

views.py import

contacto()

contacto()

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:

settings.py + gmail

settings.py + gmail

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

contactoform.html

contactoform.html

Para que nuestra aplicación sea navegable, modificamos base.html, para que quede con el siguiente menú:

base.html menu

base.html menu

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

RecetaForm y ComentarioForm

RecetaForm y ComentarioForm

Las vistas para manejar estos formularios serían estas:

nueva_receta() y nuevo_comentario()

nueva_receta() y nuevo_comentario()

Notar que se usa HttpResponseRedirect para redireccionar a una URL. Las plantillas recetaform.html y comentarioform.html serían estas:

recetaform.html

recetaform.html


comentarioform.html

comentarioform.html

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:

forms.py

forms.py

views.py (primera parte)

views.py (primera parte)

views.py (segunda parte)

views.py (segunda parte)

urls.py

urls.py

base.html

base.html

Y debemos tener las siguientes interfaces, como resultado:

Página de inicio

Página de inicio


Recetas

Recetas


Nueva receta

Nueva receta


Nuevo comentario

Nuevo comentario


Contacto

Contacto

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.

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!

Siguiente capítulo: Los archivos estáticos

Sergio Infante MonteroSergio Infante Montero para Maestros del Web.
Agrega tu comentario | Enlace permanente al artículo

Síguenos en: Twitter @maestros | Facebook Fan page

45 comentarios

Comentarios

  1. Brizuela

    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

    1. Muchas gracias Brizuela por seguir el curso :D y que bueno que te sea de utilidad

  2. damian

    muy bueno. impresionado de que con Django sin escribir tanto código realizas muchas funcionalidades

  3. Django es super genial :3

  4. hugo castañeda

    excelente continuo leyendo los capítulos todos los lunes

  5. Jugalvez

    Genial tutorial, creo que ya es hora de realizar un proyecto completo para practicar como se debe :)

  6. Excelente colección de tutoriales, muy claros y específicos. Y las cheatsheets no tienen precio. ¡Gracias por compartir con nosotros todo esto!

    1. Al final del curso los juntare todos para que tenga un documento muy completo. :)

  7. Oh my god CSS yeah :3

  8. Gracias a todos por sus comentarios, es un agrado que les guste :)

  9. daniel

    Hola.

    Aquí pueden encontrar los slides del video que recomienda @neosergio.

    http://yergler.net/2012/pycon-forms/

  10. Yohani

    Por favor, muy bueno el curso, cuando continúa?????

    1. El proximo lunes Yohani :)

  11. Realmente muy bueno, y sencillo. Despues del curso, cuando me haga mas tiempo, a leer la docu oficial ;)

  12. joel

    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?

    1. El ultimo capitulo hablará sobre ello

  13. Edgar

    @neosergio en el curso si vamos a hablar de la gestión de usuario???

  14. 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

  15. Diego

    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 %}

    1. 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

    2. Podrías revisar este enlace, te será de mucha ayuda para incluir Javascript (http://www.dajaxproject.com/)

  16. Matias

    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?

    1. Jorge

      Matias, yo lo tengo con dos return y no tengo problemas, verifica que estes importanto HttpResponse. Saludos.

  17. jorge

    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

    1. 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)

  18. Matias

    Ya solucione mi problema. Habia puesto mal la identacion del else, lo puse para el segundo if.

    1. Que bueno, no te olvides revisar el código del proyecto en Github para comparar tus resultados (http://neosergio.github.com/recetario_mdw/)

  19. 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!

    1. Matias

      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.

    2. 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/)

  20. Edgar

    Fantástico el material del tema, pero como hago un formulario para editar una receta??

    1. 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)

  21. Edgar

    Como elimino una receta

  22. Elio

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

  23. mxonda

    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.

  24. 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.

  25. Ernesto

    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

  26. JONATHAN OLIER MIRANDA

    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.

  27. Diego Rodriguez

    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…

  28. ruvi

    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!!

  29. edwar

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

  30. Francisco Morales

    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

Los comentarios de este post están cerrados. Si quieres seguir la discusión, debatir, criticar, sugerir o expandir el tema te invitamos a hacerlo en tu propio blog, en twitter o donde puedas publicar. No olvides enlazar a este post para que sigamos la conversación y se genere un trackback.