Ejemplos de web2pyTM
Examples:
simple |
sesión |
plantilla |
layout |
formulario |
base de datos |
cache |
pruebas |
streaming |
xmlrpc
Ejemplos simples
Aquí hay algunos ejemplos completos y funcionales que explican la sintaxis básica del framework.
Puede presionar en las palabras claves de web2py (¡en el código resaltado!) para tener información.
Ejemplo 1
En el contrlador: simple_examples.py
1. 2. | def hello1(): return "Hello World" |
Si la función de controlador devuelve una cadena, esta es el cuerpo de la página generada.
Pruebelo aquí: hello1
Ejemplo 2
En el controlador: simple_examples.py
1. 2. | def hello2(): return T("Hello World") # hola mundo! |
La función T() marca las cadenas que necesitan ser traducidas. Los diccionarios de traducción pueden ser creados en /admin/default/design
Pruebelo aquí: hello2
Ejemplo 3
En el controlador: simple_examples.py
1. 2. | def hello3(): return dict(message=T("Hello World")) |
y la vista: simple_examples/hello3.html
1. 2. 3. | {{extend 'layout.html'}} <h1>{{=message}}</h1>
|
Si devuelve un diccionario, las variables definidas como claves del diccionario son visibles a la vista (plantilla).
Pruebelo aquí: hello3
Las acciones pueden ser generadas en otros formatos como JSON, hello3.json, and XML, hello3.xml
Ejemplo 4
En el controlador: simple_examples.py
1. 2. 3. | def hello4(): response.view='simple_examples/hello3.html' return dict(message=T("Hello World")) |
Puede cambiar la vista, pero lo predeterminado es /[controller]/[function].html. Si la predeterminada no se encuentra web2py trata de generar la página usando la vista generic.html.
Pruebelo aquí: hello4
Ejemplo 5
En el controlador: simple_examples.py
1. 2. | def hello5(): return HTML(BODY(H1(T('Hello World'),_style="color: red;"))).xml() # .xml to serialize |
Puede también generar HTML usando objetos ayudantes HTML, BODY, H1, etc. Cada uno de estas etiquetas es una clase y la vista conoce como representarla. El método .xml() las serializa y produce el código html/xml para la página.
Cada etiqueta, DIV por ejemplo, toma tres tipos de argumentos:
- agrumentos sin nombre, que corresponden a las etiquetas anidadas
- argumentos cuyo nombre empieza con '_'. Estos son mapeados ciegamente en los atributos de etiquetas y el '_' es removido. atributos sin valor como "READONLY" pueden ser creados con "_readonly=ON".
- argumentos cuyo nombre no empieza con '_'. Tienen un significado especial. Ver más adelante "value=" para etiquetas INPUT, TEXTAREA, SELECT.
Pruebelo aquí: hello5
Ejemplo 6
En el controlador: simple_examples.py
1. 2. 3. | def hello6(): response.flash=T("Hello World in a flash!") return dict(message=T("Hello World")) |
response.flash permite que ud. muestre un mensaje parpadeante al usuario cuando la página es devuelta. Use session.flash en vez de response.flash para mostrar un mensaje luego de una redirección. Con el layout por defecto, puede presionar sobre el mensaje parpadeante para que desaparezca.
Pruebelo aquí: hello6
Ejemplo 7
En el controlador: simple_examples.py
Aqui estamos mostrando los objetos del requerimiento, sesión y respuesta usando la plantilla predeterminada generic.html.
Pruebelo aquí: status
Ejemplo 8
En el controlador: simple_examples.py
Puede hacer redirecciones.
Pruebelo aquí: redirectme
Ejemplo 9
En el controlador: simple_examples.py
1. 2. | def raisehttp(): raise HTTP(400,"internal error") |
Puede lanzar excepciones HTTP para devolver mensaje de error.
Pruebelo aquí: raisehttp
Ejemplo 10
En el controlador: simple_examples.py
1. 2. 3. | def raiseexception(): 1/0 return 'oops' |
Si una excepción ocurre (otra que HTTP) un ticket es generado y el evento es registrado para el administrador. Estos tickets y bitácoras pueden ser accedidos, revisados y eliminados en cualquier momento.
Pruebelo aquí: raiseexception
Ejemplo 11
En el controlador: simple_examples.py
1. 2. 3. 4. | def servejs(): import gluon.contenttype response.headers['Content-Type']=gluon.contenttype.contenttype('.js') return 'alert("This is a Javascript document, it is not supposed to run!");' |
Puede servir algo distinto a páginas HTML al cambiar el contenttype (tipo de contenido) vía los response.headers (encabezados de respuesta). El módulo gluon.contenttype puede ayudarlo a darse cuenta el tipo del archivo a servir. NOTA: esto no es necesario para los archivos estáticos salvo que desee requerir autorización.
Pruebelo aquí: servejs
Ejemplo 12
En el controlador: simple_examples.py
1. 2. | def makejson(): return response.json(['foo', {'bar': ('baz', None, 1.0, 2)}]) |
Si usa Ajax, web2py incluye gluon.contrib.simplejson, desarrollado por Bob Ippolito. Este módulo provee una manera rápida y fácil de servir contenidos asincrónicos a su página Ajax. gluon.simplesjson.dumps(...) puede serializar la mayoría de los tipos de Python a JSON. gluon.contrib.simplejson.loads(...) realiza la operación inversa.
Pruebelo aquí: makejson
Nuevo en web2py 1.63: Cualquier acción normal devolviendo un dict es automáticamente serializada a JSON si se agrega '.json' a la URL.
Ejemplo 13
En el controlador: simple_examples.py
1. 2. 3. 4. 5. 6. 7. 8. 9. | def makertf(): import gluon.contrib.pyrtf as q doc=q.Document() section=q.Section() doc.Sections.append(section) section.append('Section Title') section.append('web2py is great. '*100) response.headers['Content-Type']='text/rtf' return q.dumps(doc) |
web2py también incluye gluon.contrib.pyrtf, desarrollado por Simon Cusack y revisado por Grant Edwards. Este módulo permite generar documentos Rich Text Format (Texto de Formato Enriquecido) incluyendo texto coloreado y formateado junto con imágenes.
Pruebelo aquí: makertf
En el controlador: simple_examples.py
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. | def rss_aggregator(): import datetime import gluon.contrib.rss2 as rss2 import gluon.contrib.feedparser as feedparser d = feedparser.parse("http://rss.slashdot.org/Slashdot/slashdot/to")
rss = rss2.RSS2(title=d.channel.title, link = d.channel.link, description = d.channel.description, lastBuildDate = datetime.datetime.now(), items = [ rss2.RSSItem( title = entry.title, link = entry.link, description = entry.description, # guid = rss2.Guid('unkown'), pubDate = datetime.datetime.now()) for entry in d.entries] ) response.headers['Content-Type']='application/rss+xml' return rss2.dumps(rss) |
web2py incluyegluon.contrib.rss2, desarrollado por Dalke Scientific Software, el cual genera RSS2 feeds, y
gluon.contrib.feedparser, desarrollado por Mark Pilgrim, el cual recolecta RSS y ATOM feeds. El controlador de arriba recolecta feeds de slashdot y hace uno nuevo.
Pruebelo aquí: rss_aggregator
Ejemplo 15
En el controlador: simple_examples.py
1. 2. 3. 4. 5. 6. 7. 8. 9. | from gluon.contrib.markdown import WIKI
def ajaxwiki(): form=FORM(TEXTAREA(_id='text'),INPUT(_type='button',_value='markdown', _onclick="ajax('ajaxwiki_onclick',['text'],'html')")) return dict(form=form,html=DIV(_id='html'))
def ajaxwiki_onclick(): return WIKI(request.vars.text).xml() |
web2py también incluye gluon.contrib.markdown (markdown2) el que convierte WIKI markup a HTML siguiendo esta sintáxis. In this example we added a fancy ajax effect.
Pruebelo aquí: ajaxwiki
Ejemplos de Sesión
Ejemplo 16
En el controlador: session_examples.py
y en la vista: session_examples/counter.html
1. 2. 3. 4. 5. 6. | {{extend 'layout.html'}} <h1>session counter</h1>
<h2>{{for i in range(counter):}}{{=i}}...{{pass}}</h2>
<a href="{{=URL(r=request)}}">click me to count</a> |
Presione para contar. El session.counter es persistente para este usario y aplicación. Cada aplicación dentro del sistema tiene su propio y separado gestor de sesión.
Pruebelo aquí: counter
Ejemplos de plantillas
Ejemplo 17
En el controlador: template_examples.py
1. | def variables(): return dict(a=10, b=20) |
y en la vista: template_examples/variables.html
1. 2. 3. 4. | {{extend 'layout.html'}} <h1>Your variables</h1> <h2>a={{=a}}</h2> <h2>a={{=b}}</h2> |
Una vista (también conocida como template o plantilla) es simplemente un archivo HTML con etiquetas {{...}}. Puede poner CUALQUIER código python dentro de las etiquetas, no necesita sangrar (indentar) pero debe usar pass para cerrar los bloques. La vista es transformada a código python y es ejecutada. {{=a}} imprime a.xml() o escape(str(a)).
Pruebelo aquí: variables
Ejemplo 18
En el controlador: template_examples.py
1. | def test_for(): return dict() |
y en la vista: template_examples/test_for.html
1. 2. 3. 4. 5. 6. | {{extend 'layout.html'}} <h1>For loop</h1>
{{for number in ['one','two','three']:}} <h2>{{=number.capitalize()}}<h2> {{pass}} |
Puede hacer bucles while y ciclos for.
Pruebelo aquí: test_for
Ejemplo 19
En el controlador: template_examples.py
1. | def test_if(): return dict() |
y en la vista: template_examples/test_if.html
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. | {{extend 'layout.html'}} <h1>If statement</h1>
{{ a=10 }}
{{if a%2==0:}} <h2>{{=a}} is even</h2> {{else:}} <h2>{{=a}} is odd</h2> {{pass}} |
Puede hacer condiciones if, elif, else.
Pruebelo aquí: test_if
Ejemplo 20
En el controlador: template_examples.py
1. | def test_try(): return dict() |
y en la vista: template_examples/test_try.html
1. 2. 3. 4. 5. 6. 7. 8. | {{extend 'layout.html'}} <h1>Try... except</h1>
{{try:}} <h2>a={{=1/0}}</h2> {{except:}} infinity</h2> {{pass}} |
Puede hacer try, except, finally (manejo de excepciones).
Pruebelo aquí: test_try
Ejemplo 21
En el controlador: template_examples.py
1. | def test_def(): return dict() |
y en la vista: template_examples/test_def.html
1. 2. 3. 4. 5. 6. 7. | {{extend 'layout.html'}} {{def itemlink(name):}}<li>{{=A(name,_href=name)}}</li>{{return}} <ul> {{itemlink('http://www.google.com')}} {{itemlink('http://www.yahoo.com')}} {{itemlink('http://www.nyt.com')}} </ul> |
También puede escribir funciones en HTML.
Pruebelo aquí: test_def
Ejemplo 22
En el controlador: template_examples.py
1. | def escape(): return dict(message='<h1>text is escaped</h1>') |
y en la vista: template_examples/escape.html
1. 2. 3. 4. 5. | {{extend 'layout.html'}} <h1>Strings are automatically escaped</h1>
<h2>Message is</h2> {{=message}} |
El argumento de {{=...}} siempre es escapado salvo que sea un objeto con método .xml() como un enlace, A(...), un FORM(...), un bloque XML(...), etc.
Pruebelo aquí: escape
Ejemplo 23
En el controlador: template_examples.py
1. 2. | def xml(): return dict(message=XML('<h1>text is not escaped</h1>')) |
y en la vista: template_examples/xml.html
1. 2. 3. 4. 5. | {{extend 'layout.html'}} <h1>XML</h1>
<h2>Message is</h2> {{=message}} |
Si no desea escapar el argumento de {{=...}} marquelo como XML.
Pruebelo aquí: xml
Ejemplo 24
En el controlador: template_examples.py
y en la vista: template_examples/beautify.html
1. 2. 3. 4. 5. | {{extend 'layout.html'}} <h1>BEAUTIFY</h1>
<h2>Message is</h2> {{=message}} |
Puede usar BEAUTIFY para tornar listas y diccionarios a HTML organizado.
Pruebelo aquí: beautify
Layout Examples
Ejemplo 25
En el controlador: layout_examples.py
1. 2. 3. 4. 5. 6. | def civilized(): response.menu=[['civilized',True,URL(r=request,f='civilized')], ['slick',False,URL(r=request,f='slick')], ['basic',False,URL(r=request,f='basic')]] response.flash='you clicked on civilized' return dict(message="you clicked on civilized") |
y en la vista: layout_examples/civilized.html
1. 2. 3. | {{extend 'layout_examples/layout_civilized.html'}} <h2>{{=message}}</h2> <p>{{for i in range(1000):}}bla {{pass}} </p> |
Puede especificar el archivo de layout al comienzo de su vista. Un archivo Layout civilizado es una vista que contiene {{include}} en algún lugar.
Pruebelo aquí: civilized
Ejemplo 26
En el controlador: layout_examples.py
1. 2. 3. 4. 5. 6. | def slick(): response.menu=[['civilized',False,URL(r=request,f='civilized')], ['slick',True,URL(r=request,f='slick')], ['basic',False,URL(r=request,f='basic')]] response.flash='you clicked on slick' return dict(message="you clicked on slick") |
y en la vista: layout_examples/slick.html
1. 2. 3. | {{extend 'layout_examples/layout_sleek.html'}} <h2>{{=message}}</h2> {{for i in range(1000):}}bla {{pass}} |
Lo mismo aquí, pero usando una plantilla diferente.
Pruebelo aquí: slick
Ejemplo 27
En el controlador: layout_examples.py
1. 2. 3. 4. 5. 6. | def basic(): response.menu=[['civilized',False,URL(r=request,f='civilized')], ['slick',False,URL(r=request,f='slick')], ['basic',True,URL(r=request,f='basic')]] response.flash='you clicked on basic' return dict(message="you clicked on basic") |
y en la vista: layout_examples/basic.html
1. 2. 3. | {{extend 'layout.html'}} <h2>{{=message}}</h2> {{for i in range(1000):}}bla {{pass}} |
'layout.html' es la plantilla predeterminada, cada aplicación tiene una copia de ella.
Pruebelo aquí: basic
Ejemplo 28
En el controlador: form_examples.py
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. | def form(): form=FORM(TABLE(TR("Su nombre:",INPUT(_type="text",_name="name",requires=IS_NOT_EMPTY())), TR("Su correo:",INPUT(_type="text",_name="email",requires=IS_EMAIL())), TR("¿Admin?",INPUT(_type="checkbox",_name="admin")), TR("¿Seguro?",SELECT('yes','no',_name="sure",requires=IS_IN_SET(['yes','no']))), TR("Perfil",TEXTAREA(_name="profile",value="write something here")), TR("",INPUT(_type="submit",_value="SUBMIT")))) if form.accepts(request.vars,session): response.flash="formulario aceptado" elif form.errors: response.flash="formulario inválido" else: response.flash="por favor complete el formulario" return dict(form=form,vars=form.vars) |
Puede usar ayudantes HTML como FORM, INPUT, TEXTAREA, OPTION, SELECT para construir un formulario. El atributo "value=" establece el valor inicial de un campo (también funciona para TEXTAREA y OPTION/SELECT) y el atributo "requires" establece los validadores.
FORM.accepts(..) intenta validar el formulario y, si hay éxito, almacena las variables vars en form.vars. Si hay fallo el mensaje de error se almacena en form.errors y se muestra en el formulario.
Pruebelo aquí: form
Ejemplo con Bases de Datos
Puede encontrar más ejemplos de la Capa de Abstracción de la Base de Datos aquí
Vamos a crear un modelo simple con clientes (users), perros (dogs), productos (products) y compras (purchases) -la base de datos de una tienda de mascotas-. Los clientes pueden tener muchos perros (UNO A MUCHOS), pueden comprar muchos productos y cada producto puede tener muchos compradores (MUCHOS A MUCHOS).
Ejemplo 29
en el modelo: db.py
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. | db=DAL('sqlite://storage.db')
# clientes (nombre, email) db.define_table('users', Field('name'), Field('email'))
# UN (cliente) A MUCHOS (perros) # perros (id_propietario, nombre, tipo, vacunado, fotografía) db.define_table('dogs', Field('owner_id',db.users), Field('name'), Field('type'), Field('vaccinated','boolean',default=False), Field('picture','upload',default=''))
# productos (nombre, descripción) db.define_table('products', Field('name'), Field('description','text'))
# MUCHOS (clientes) A MUCHOS (productos) # compras (id_comprador, id_producto, cantidad) db.define_table('purchases', Field('buyer_id',db.users), Field('product_id',db.products), Field('quantity','integer'))
purchased=((db.users.id==db.purchases.buyer_id)&(db.products.id==db.purchases.product_id))
# Validadores: db.users.name.requires=IS_NOT_EMPTY() # nombre de cliente no vacio db.users.email.requires=[IS_EMAIL(), IS_NOT_IN_DB(db,'users.email')] # email válido y no existente db.dogs.owner_id.requires=IS_IN_DB(db,'users.id','users.name') # propietario sea cliente existente db.dogs.name.requires=IS_NOT_EMPTY() # nombre del perro no vacio db.dogs.type.requires=IS_IN_SET(['pequeño','mediano','grande']) # tipo de perro db.purchases.buyer_id.requires=IS_IN_DB(db,'users.id','users.name') # comprador sea cliente existente db.purchases.product_id.requires=IS_IN_DB(db,'products.id','products.name') # producto existente db.purchases.quantity.requires=IS_INT_IN_RANGE(0,10) # cantidad en el rango 0 a 10 |
Las tablas son creadas si no existen (try... except).
Aqui "purchased" es un objeto SQLQuery (consulta sql), "db(purchased)" serán los objetos SQLSet (conjunto de resultados sql). Un SQLSet puede ser seleccionado (select), actualizado (update) y eliminado (delete). SQLSets también puede ser intersectado. Los tipos de campos permitidos son string, integer, password, text, blob, upload, date, time, datetime, references(*), e id(*). El campo id está por defecto y no debe ser declarado. references es para uno a muchos o muchos a muchos como en el ejemplo superior. Para campos strings debería especificar la longitud u obtendrá length=32.
Puede usar db.tablename.fieldname.requires= para establecer las restricciones a los valores de los campos. Estas restricciones son automáticamente convertidas a widgets (artefactos) al generar los formularios desde las tablas con SQLFORM(db.tablename).
define_tables crea la tabla e intenta una migración si la tabla ha sido modificada o si el nombre de la base de datos ha cambiado desde la última vez. Si ya sabe que ya tiene la tabla en la base de datos y no desea intentar una migración, use como último argumento de define_table migrate=False.
Ejemplo 30
En el controlador: database_examples.py
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. | response.menu=[['Registrar Usuario',False,URL(r=request,f='register_user')], ['Registrar Perro',False,URL(r=request,f='register_dog')], ['Registrar Producto',False,URL(r=request,f='register_product')], ['Comprar Producto',False,URL(r=request,f='buy')]]
def register_user(): ### crea e inserta un formulario form para la tabla users form=SQLFORM(db.users) ### si el formulario es correcto, realizar el insert if form.accepts(request.vars,session): response.flash='nuevo registro insertado' ### y obtener una lista de todos los usuarios records=SQLTABLE(db().select(db.users.ALL)) return dict(form=form,records=records) |
y en la vista: database_examples/register_user.html
1. 2. 3. 4. 5. 6. | {{extend 'layout_examples/layout_civilized.html'}}
<h1>User registration form</h1> {{=form}} <h2>Current users</h2> {{=records}} |
Este es un formulario simple de registración de usuario. SQLFORM toma una tabla y devuelve el formulario de entrada correspondiente con validadores, etc. SQLFORM.accepts es similar a FORM.accepts pero, si el formulario es validado, el insert correspondiente también es realizado. SQLFORM puede también hacer modificaciones y editar si un registro es pasado como su segundo argumento.
SQLTABLE en cambio convierte unconjunto de registros (resultado de un select) en una tabla HTML con enlaces especificados por sus parámetros opcionales.
El response.menu arriba es simplemente una variable usada por el layout para hacer el menú de navegación para todas las funciones en este controlador.
Pruebelo aquí: register_user
Ejemplo 31
En el controlador: database_examples.py
1. 2. 3. 4. 5. 6. 7. | def register_dog(): form=SQLFORM(db.dogs) if form.accepts(request.vars,session): response.flash='new record inserted' download=URL(r=request,f='download') # to see the picture records=SQLTABLE(db().select(db.dogs.ALL),upload=download) return dict(form=form,records=records) |
y en la vista: database_examples/register_dog.html
1. 2. 3. 4. 5. 6. | {{extend 'layout_examples/layout_civilized.html'}}
<h1>Dog registration form</h1> {{=form}} <h2>Current dogs</h2> {{=records}} |
Here is a dog registration form. Notice that the "image" (type "upload") field is rendered into a <INPUT type="file"> html tag. SQLFORM.accepts(...) handles the upload of the file into the uploads/ folder.
Pruebelo aquí: register_dog
Ejemplo 32
En el controlador: database_examples.py
1. 2. 3. 4. 5. 6. | def register_product(): form=SQLFORM(db.products) if form.accepts(request.vars,session): response.flash='new record inserted' records=SQLTABLE(db().select(db.products.ALL)) return dict(form=form,records=records) |
y en la vista: database_examples/register_product.html
1. 2. 3. 4. 5. 6. | {{extend 'layout_examples/layout_civilized.html'}}
<h1>Product registration form</h1> {{=form}} <h2>Current products</h2> {{=records}} |
Nada nuevo aquí.
Pruebelo aquí: register_product
Ejemplo 33
En el controlador: database_examples.py
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. | def buy(): form=FORM(TABLE(TR("Buyer id:",INPUT(_type="text",_name="buyer_id",requires=IS_NOT_EMPTY())), TR("Product id:",INPUT(_type="text",_name="product_id",requires=IS_NOT_EMPTY())), TR("Quantity:",INPUT(_type="text",_name="quantity",requires=IS_INT_IN_RANGE(1,100))), TR("",INPUT(_type="submit",_value="Order")))) if form.accepts(request.vars,session): ### verifica si el usuario está en la base de datos if len(db(db.users.id==form.vars.buyer_id).select())==0: form.errors.buyer_id="comprador no está en la base de datos" ### verifica si el producto está en la base de datos if len(db(db.products.id==form.vars.product_id).select())==0: form.errors.product_id="producto no está en la base de datos" ### si no hay error if len(form.errors)==0: ### obtener una lista de las compras similares del usuario purchases=db((db.purchases.buyer_id==form.vars.buyer_id)& (db.purchases.product_id==form.vars.product_id)).select() ### si la lista contiene un registro, actualizarlo if len(purchases)>0: purchases[0].update_record(quantity=purchases[0].quantity+form.vars.quantity) ### o insertar un nuevo registro en la tabla else: db.purchases.insert(buyer_id=form.vars.buyer_id, product_id=form.vars.product_id, quantity=form.vars.quantity) response.flash="producto comprado!" if len(form.errors): response.flash="valores inválidos en el formulario!" ### ahora obtener una lista de todas las compras records=db(purchased).select(db.users.name,db.purchases.quantity,db.products.name) return dict(form=form,records=SQLTABLE(records),vars=form.vars,vars2=request.vars) |
y en la vista: database_examples/buy.html
1. 2. 3. 4. 5. 6. 7. | {{extend 'layout_examples/layout_civilized.html'}} <h1>Purchase form</h1> {{=form}} [ {{=A('reset purchased',_href=URL(r=request,f='reset_purchased'))}} | {{=A('delete purchased',_href=URL(r=request,f='delete_purchased'))}} ]<br/> <h2>Current purchases (SQL JOIN!)</h2> <p>{{=records}}</p> |
Aquí hay un ejemplo de formulario de compra más sofisticado. Verifica que el comprador y el producto esten en la base de datos y acualiza el registro correspondiente o inserta una nueva compra. También hace un JOIN para listar todas las compras.
Pruebelo aquí: buy
Ejemplo 34
En el controlador: database_examples.py
1. 2. 3. | def delete_purchased(): db(db.purchases.id>0).delete() redirect(URL(r=request,f='buy')) |
Pruebelo aquí:
delete_purchased
Ejemplo 35
En el controlador: database_examples.py
1. 2. 3. | def reset_purchased(): db(db.purchases.id>0).update(quantity=0) redirect(URL(r=request,f='buy')) |
Esto es una actualización sobre un SQLSet. (db.purchase.id>0 identifica un conjunto conteniendo solo las db.purchases.)
Pruebelo aquí: reset_purchased
Ejemplo 36
En el controlador: database_examples.py
Este controlador permite a los usuarios descargar las fotos subidas de los perros.
Recordar la sentencia upload=URL(...'download'...) en la función de registro de perros. Notar que en la ruta URL /application/controller/function/a/b/etc a, b, etc son pasadas al controlador como request.args[0], request.args[1], etc. Dado que la URL es validada request.args[] siempre contiene nombres de archivos válidos y no '~' o '..' etc. Esto es útil para permitir a los visitantes enlazar los archivos.
Ejemplos de Cache
Ejemplo 37
En el controlador: cache_examples.py
1. 2. 3. 4. | def cache_in_ram(): import time t=cache.ram('time',lambda:time.ctime(),time_expire=5) return dict(time=t,link=A('click to reload',_href=URL(r=request))) |
La salida de lambda:time.ctime() es mantenida en la cache de ram por 5 segundos. La cadena 'time' es usada como clave de cache.
Pruebelo aquí: cache_in_ram
Ejemplo 38
En el controlador: cache_examples.py
1. 2. 3. 4. | def cache_on_disk(): import time t=cache.disk('time',lambda:time.ctime(),time_expire=5) return dict(time=t,link=A('click to reload',_href=URL(r=request))) |
La salida de lambda:time.ctime() es almacenada en la cached de disco (usando el módulo shelve) por 5 segundos.
Pruebelo aquí: cache_on_disk
Ejemplo 39
En el controlador: cache_examples.py
1. 2. 3. 4. 5. | def cache_in_ram_and_disk(): import time t=cache.ram('time',lambda:cache.disk('time', lambda:time.ctime(),time_expire=5),time_expire=5) return dict(time=t,link=A('click to reload',_href=URL(r=request))) |
La salida de lambda:time.ctime() es almacenada en la cached de disco (usando el módulo shelve) por 5 segundos.
web2py mira en ram primero y si no está ahí mira en el disco. Si no está en el disco llama a la función. EWsto es útil en ambientes multiproceso. Los dos tiempos no tienen por que ser los mismos.
Pruebelo aquí: cache_in_ram_and_disk
Ejemplo 40
En el controlador: cache_examples.py
1. 2. 3. 4. 5. | @cache(request.env.path_info,time_expire=5,cache_model=cache.ram) def cache_controller_in_ram(): import time t=time.ctime() return dict(time=t,link=A('click to reload',_href=URL(r=request))) |
Here the entire controller (dictionary) is cached in ram for 5 seconds. The result of a select cannot be cached unless it is first serialized into a table lambda:SQLTABLE(db().select(db.users.ALL)).xml(). You can read below for an even better way to do it.
Pruebelo aquí: cache_controller_in_ram
Ejemplo 41
En el controlador: cache_examples.py
1. 2. 3. 4. 5. | @cache(request.env.path_info,time_expire=5,cache_model=cache.disk) def cache_controller_on_disk(): import time t=time.ctime() return dict(time=t,link=A('click to reload',_href=URL(r=request))) |
Here the entire controller (dictionary) is cached on disk for 5 seconds. This will not work if the dictionary contains unpickleable objects.
Pruebelo aquí: cache_controller_on_disk
Ejemplo 42
En el controlador: cache_examples.py
1. 2. 3. 4. 5. 6. | @cache(request.env.path_info,time_expire=5,cache_model=cache.ram) def cache_controller_and_view(): import time t=time.ctime() d=dict(time=t,link=A('click to reload',_href=URL(r=request))) return response.render(d) |
response.render(d) renders the dictionary inside the controller, so everything is cached now for 5 seconds. This is best and fastest way of caching!
Pruebelo aquí: cache_controller_and_view
Ejemplo 43
En el controlador: cache_examples.py
1. 2. 3. 4. 5. 6. | def cache_db_select(): import time db.users.insert(name='somebody',email='gluon@mdp.cti.depaul.edu') records=db().select(db.users.ALL,cache=(cache.ram,5)) if len(records)>20: db(db.users.id>0).delete() return dict(records=records) |
The results of a select are complex unpickleable objects that cannot be cached using the previous method, but the select command takes an argument cache=(cache_model,time_expire) and will cache the result of the query accordingly. Notice that the key is not necessary since key is generated based on the database name and the select string.
Pruebelo aquí: cache_db_select
Ajax Examples
Ejemplo 44
En el controlador: ajax_examples.py
In view: ajax_examples/index.html
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. | {{extend 'layout.html'}}
<p>Type something and press the button. The last 10 entries will appear sorted in a table below.</p>
<form> <INPUT type="text" id='q' value="web2py"/> <INPUT type="button" value="submit" onclick="ajax('{{=URL(r=request,f='data')}}',['q'],'target');"/> </form> <br/> <div id="target"></div> |
The javascript function "ajax" is provided in "web2py_ajax.html" and included by "layout.html". It takes three arguments, a url, a list of ids and a target id. When called, it sends to the url (via a get) the values of the ids and display the response in the value (of innerHTML) of the target id.
Pruebelo aquí: index
Ejemplo 45
En el controlador: ajax_examples.py
1. 2. 3. | def flash(): response.flash='this text should appear!' return dict() |
Pruebelo aquí: flash
Ejemplo 46
En el controlador: ajax_examples.py
1. 2. | def fade(): return dict() |
In view: ajax_examples/fade.html
1. 2. 3. 4. 5. 6. 7. 8. | {{extend 'layout.html'}}
<form> <input type="button" onclick="fade('test',-0.2);" value="fade down"/> <input type="button" onclick="fade('test',+0.2);" value="fade up"/> </form>
<div id="test">{{='Hello World '*100}}</div> |
Pruebelo aquí: fade
Excel-like spreadsheet via Ajax
Web2py includes a widget that acts like an Excel-like spreadsheet and can be used to build forms
[
read more].
Testing Examples
Ejemplo 47
Using the Python doctest notation it is possible to write tests for all controller functions. Tests are then run via the administrative interface which generates a report. Here is an example of a test in the code:
1. 2. 3. 4. 5. 6. 7. 8. | def index(): ''' This is a docstring. The following 3 lines are a doctest: >>> request.vars.name='Max' >>> index() {'name': 'Max'} ''' return dict(name=request.vars.name) |
Streaming Examples
Ejemplo 48
It is very easy in web2py to stream large files. Here is an example of a controller that does so:
1. 2. 3. 4. | def streamer(): import os path=os.path.join(request.folder,'private','largefile.mpeg4') return response.stream(open(path,'rb'),chunk_size=4096) |
By default all static files and files stored in 'upload' fields in the database are streamed when larger than 1MByte.
web2py automatically and transparently handles PARTIAL_CONTENT and RANGE requests.
XML-RPC Examples
Ejemplo 49
Web2py has native support for the XMLRPC protocol. Below is a controller function "handler" that exposes two functions, "add" and "sub" via XMLRPC. The controller "tester" executes the two function remotely via xmlrpc.
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. | from gluon.tools import Service service = Service(globals())
@service.xmlrpc def add(a,b): return a+b
@service.xmlrpc def sub(a,b): return a-b
def call(): return service()
def tester(): import xmlrpclib server=xmlrpclib.ServerProxy('http://hostname:port/app/controller/call/xmlrpc') return str(server.add(3,4)+server.sub(3,4)) |
Read more here