Desarrollo web con Python y Web.py – parte 3

Formularios en Web.py

El módulo form de web.py permite generar formas html, obtener entrada del usuario, y validarlo antes de su procesamiento o su inclusión en una base de datos.

El módulo form define dos clases pricipales:
Form: crea una instancia con una o más entradas, y los validadores opcionales.
Input: crea una instancia con el nombre de una variable, y los argumentos opcionales y validadores.

La clase Input es una subclase de las siguientes entradas html (tipo de elemento html en paréntesis):
* Texbox: Entrada de formulario de una sola línea (<input type=”text”></input>).
* Password: Entrada de formulario de una sola línea que esconde el texto (<input type=”password”></input>).
* Textarea: Entrada de formulario multilínea o múltiples líneas (<input type=”textarea”></input>).
* Dropdown: Lista de entrada excluyente (<select> y <option>)
* Radio: Entrada mutuamente excluyente para algunas opciones (<input type=”radio”></input>)
* Checkbox: Entrada binaria. Si son varias entradas relacionadas, checkbox no es excluyente (<input type=”checkbox”></input>)
* Button: Botón de formulario (button)

Creamos un programa básico de logueo:

 1 #!/usr/bin/env python
 2 # -*- coding: UTF-8 -*-
 3 import web
 4 from web import form
 5
 6 urls = (
 7   '/', 'ingreso'
 8 )
 9
 10 app = web.application(urls, globals())
 11
 12 # Creamos nustro formulario:
 13 login = form.Form(
 14   form.Textbox('usuario'),
 15   form.Password('clave'),
 16   form.Button('Iniciar'),
 17 )
 18
 19 class ingreso:
 20   def GET(self):
 21     f = login()
 22     return f.render()
 23
 24 def main():
 25   app.run()
 26   return 0
 27
 28 if __name__ == "__main__": main()

Esto nos mostraría una página así:

Si reemplazamos la línea 22 “return f.render()” por “print f.render()”, en El Método GET, nos creará la siguiente salida:

 <table>
 <tr><th><label for="usuario">usuario</label></th><td><input type="text" id="usuario" name="usuario"/></td></tr>
 <tr><th><label for="clave">clave</label></th><td><input type="password" id="clave" name="clave"/></td></tr>
 <tr><th><label for="Iniciar"></label></th><td><button id="Iniciar" name="Iniciar">Iniciar</button></td></tr>
 </table>

CARACTERÍSTICAS DE LOS ELEMENTOS DE ENTRADA:

Las entradas de formulario soportan varios atributos adicionales.

form.Texbox("fistname", form.notnull, class_="Entrada_de_texto", pre="pre", post="post", destription"string", value="", id="nombre_de_id")

fistname: hace referencia al atributo name de los elementos de formulario.
form.notnull: poner validadores primero, seguido por los atributos opcionales.
class_=”textEntry”: da un nombre de clase CSS, para el cuadro de texto.
pre=”pre”: text antes del cuadro de texto.
pos=”post”: text inmediatamente después del cuadro de texto.
description=”string”: Describe el campo. Por defecto establece (firstname).
value=””: valor por defecto. Puede establecer un valor por defecto.
id=”nombre_de_id”: especifica el id.
size=”pixeles”: Tamaño en pixeles del control.
maxlength=”num”: Máximo número de caracteres para los controles de texto y de password.

Por ejemplo, si modificamos nuestro formulario, agregándole:

 12 # Creamos nuestro formulario:
 13 login = form.Form(
 14   form.Textbox('usuario', form.notnull, description="Username", class_="textEntry",\
 15   value="nombre de usuario", id="cajatext", post="despues", pre="antes", size="10"),
 16   form.Password('clave', description="Password", maxlength="4", size="10"),
 17   form.Button('Iniciar'),
 18 )

Este ejemplo dibujaría algo como:

Nos debe aparecer en html:

 <table>
 <tr><th><label for="cajatext">Username</label></th><td>antes<input name="usuario" value="nombre de usuario" class="textEntry" type="text" id="cajatext" size="10"/>despues</td></tr>
 <tr><th><label for="clave">Password</label></th><td><input maxlength="4" type="password" id="clave" name="clave" size="10"/></td></tr>
 <tr><th><label for="Iniciar"></label></th><td><button id="Iniciar" name="Iniciar">Iniciar</button></td></tr>
 </table>

CARACTERÍSTICAS DE LOS ELEMENTOS DROPDOWN (Desplegables):

Estas listas se crean con tuplas que permiten una descripción única y valor por cada elemento de la lista desplegable. P. e. un programa que muestre una lista desplegable:

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 #
 4 import web
 5 from web import form
 6
 7 urls=(
 8   '/listas', 'Lista'
 9 )
 10
 11 app = web.application(urls, globals())
 12
 13 lista = form.Form(
 14   form.Dropdown('milista', \
 15   [('valor1','1000'),('valor2','2000')])
 16 )
 17
 18 class Lista:
 19   def GET(self):
 20     l = lista()
 21     return l.render()
 22
 23
 24 def main():
 25   app.run()
 26   return 0
 27
 28 if __name__ == "__main__": main()

Si visitamos http://localhost:8080/listas. Veremos algo como:

CARACTERÍSTICAS DE LOS FORMULARIOS

Además de los validadores individuales de form.py se puede realizar validaciones de comparación de campos de nuestro formulario. Los datos validadores se pasan a una list. P.e. Un programa que valide si la cantraseña es correcta.

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 #
 4 import web
 5 from web import form
 6
 7
 8 urls=(
 9   '/suscribe', 'Suscribe'
 10 )
 11
 12 app = web.application(urls, globals())
 13
 14 formulario = form.Form(
 15   form.Textbox('username', maxlength="10"),
 16   form.Password('clave', maxlength="8",\
 17   post=" se requiere un passwod de 8 caracteres"),
 18   form.Password('valida_clave', maxlength="8", description="Repita la clave"),
 19   form.Button("Enviar"),
 20   validators = [form.Validator("La contraseña no coincide",\
 21   lambda i: i.clave == i.valida_clave)]
 22 )
 23
 24 class Suscribe:
 25   def GET(self):
 26     f = formulario()
 27     return f.render()
 28
 29 def main():
 30   app.run()
 31   return 0
 32
 33 if __name__ == "__main__":
 34   main()

UN EJEMPLO FUNCIONAL:

Creamos nuestra plantilla llamada formulario_1.html.

 1 $def with (form)
 2
 3 <form>
 4   $:form.render()
 5   <input type="submit" />
 6 </form>

Ahora creamos nuestro programa para que nos cree un formulario con el método GET, llamado formulario.py.

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 import web
 4 from web import form
 5
 6 urls = (
 7   '/', 'index'
 8 )
 9
 10 plantilla = web.template.render('./templates/')
 11
 12 app = web.application(urls, globals())
 13
 14 myform = form.Form(
 15   form.Textbox("nombre"),
 16   form.Textbox("id",
 17     form.notnull,
 18     form.regexp('\d+', 'Debe ser un dígito'),
 19     form.Validator('Debe ser más de 5', lambda x:int(x)>5)),
 20   form.Textarea('observacion'),
 21   form.Checkbox('reenviar'),
 22   form.Dropdown('prioridad', ['baja', 'media', 'alta']))
 23
 24
 25 class index:
 26   def GET(self):
 27     form = myform()
 28     return plantilla.formulario_1(form)
 29
 30
 31 if __name__ == "__main__":
 32   app.run()

Cuando lo ejecutemos nos mostrará algo como esto:

En esta segunda imagen vemos cómo enviamos los datos al hacer clic en Enviar.

Esto nos creara una salida html:

<form> <table> <tr><th><label for=”nombre”>nombre</label></th><td><input type=”text” id=”nombre” name=”nombre”/></td></tr> <tr><th><label for=”id”>id</label></th><td><input type=”text” id=”id” name=”id”/></td></tr> <tr><th><label for=”observacion”>observacion</label></th><td><textarea id=”observacion” name=”observacion”></textarea></td></tr> <tr><th><label for=”reenviar_”>reenviar</label></th><td><input type=”checkbox” id=”reenviar_” value=”” name=”reenviar”/></td></tr> <tr><th><label for=”prioridad”>prioridad</label></th><td><select id=”prioridad” name=”prioridad”> <option value=”baja”>baja</option> <option value=”media”>media</option> <option value=”alta”>alta</option> </select> </td></tr> </table> <input type=”submit” /> </form>

EJEMPLO FUNCIONAL (MODIFICADO):

Modificando nuestro ejemplo, para que no solo muestre el formulario, si no que lo evalue e imprima en pantalla los datos capturados.

Creamos una nueva plantilla llamada formulario_2.html.

 1 $def with (form)
 2
 3 <!-- cuando le doy envia me llama al método POST -->
 4 <form name="main" method="post">
 5   <!-- valid(self, value), es un método de Validator(self, msg, test, jstest=None)
 6   y de regexp(self, rexp, msg), que hacen parte del type Textbox -->
 7   $if not form.valid: <p class="error">Intenta de Nuevo</p>
 8   $:form.render()
 9   <input type="submit" />
 10 </form>

Y creamos un nuevo programa con un método POST, que capture los datos enviado por el formulario.

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 import web
 4 from web import form
 5
 6 urls = (
 7   '/', 'index'
 8 )
 9
 10 plantilla = web.template.render('./templates/')
 11
 12 app = web.application(urls, globals())
 13
 14 myform = form.Form(
 15   form.Textbox("nombre"),
 16   form.Textbox("id",
 17     form.notnull,
 18     form.regexp('\d+', 'Debe ser un dígito'),
 19     form.Validator('Debe ser más de 5', lambda x:int(x)>5)),
 20   form.Textarea('observacion'),
 21   form.Checkbox('reenviar'),
 22   form.Dropdown('prioridad', ['baja', 'media', 'alta']))
 23
 24
 25 class index:
 26   # Método de Llegada
 27   def GET(self):
 28     form = myform()
 29     return plantilla.formulario_2(form)
 30
 31   # Método POST
 32   def POST(self):
 33     form = myform()
 34     if not form.validates():
 35       return plantilla.formulario_2(form)
 36     else:
 37       # form.d.nombre y form['nombre'].value son formas equivalente
 38       # de extraer los argumentos validos del formulario.
 39       return "Gran exito! Nombre: %s, ID: %s" % (form.d.nombre, form['id'].value)
 40
 41
 42 if __name__ == "__main__":
 43   app.run()

La salida sería la siguiente, si no ingresamos ningún dato y hacemos clic en “enviar“.


su respectivo html:

 <!-- cuando le doy enviar me llama al método POST -->
 <form name="main" method="post">
 <p>Intenta de Nuevo</p>
 <table>
 <tr><th><label for="nombre">nombre</label></th><td><input type="text" id="nombre" value="" name="nombre"/></td></tr>
 <tr><th><label for="id">id</label></th><td><input type="text" id="id" value="" name="id"/><strong>Required</strong></td></tr>
 <tr><th><label for="observacion">observacion</label></th><td><textarea id="observacion" name="observacion"></textarea></td></tr>
 <tr><th><label for="reenviar_">reenviar</label></th><td><input type="checkbox" id="reenviar_" value="" name="reenviar"/></td></tr>
 <tr><th><label for="prioridad">prioridad</label></th><td><select id="prioridad" name="prioridad">
 <option selected="selected" value="baja">baja</option>
 <option value="media">media</option>
 <option value="alta">alta</option>
 </select>
 </td></tr>
 </table>
 <input type="submit" />
 </form>

Podemos llenar los datos.

Y luego hacer clic en “Enviar“.

Si no son dígitos en el campo “id”.

FORMULARIOS PARA BASES DE DATOS:

Una vez que los datos del formulario se han publicado, puede ser fácilmente puesto en una base de datos (si el esquema de base de datos tiene los nombres coherentes con su formulario webpy). Por ejemplo:

class Agregar:
 def POST(self):
   f = formulario()
   if f.validates():
     web.insert('nombre_tabla_db', **f.d)
   # No debe usar web.insert('nombre_tabla_db', **web.input()) porque los datos malintencionados podrían presentarse también
   else:
     render.foo(f)

Esto debemos tenerlo en cuenta para el manejo de bases de datos con web.py.

By: Jolth

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s