====== web.py ======
* [[http://webpy.org/|Web]]
* [[http://webpy.org/docs/0.3/|Documentación]]
===== Uso =====
==== Cómo funciona? ====
web.py se basa en la estructura de las URL de la página web. Para trabajar con este tendremos que...
- Importar el módulo ''web''.
- Indicar la estructura de la URL.
- Indicar qué clases se utilizarán mediante ''web.application''.
import web
urls = (
'/', 'index'
)
app = web.application(urls, globals())
En el código anterior estamos diciendo que queremos la URL raíz ( ''/'' ), que será gestionada por la clase ''index'', las clases que se utilizarán serán las globales del namespace actual. \\ \\
=== Indicar las URL ===
Las URL se indican a partir de una parte que es una expresión regular tal como ''/'', ''/help/faq'', ''/item/(\d+)'' (por ejemplo d+ permite una secuencia de dígitos), y otra que es el nombre de la clase que recibirá la petición (index, view...). \\
Cuando en la expresión regular utilizamos un paréntesis indicamos que ese elemento va a ser utilizado luego, a eso se le llama **capturar**. \\
Para la segunda parte podemos indicar, por ejemplo, ''welcomes.hello'' (modulo ''welcomes'' clase ''hello''), ''get_\1'' donde ese \1 se reemplazará por la primera parte capturada de la expresión regular.
=== Clases correspondientes a los elementos de la URL ===
Las clases que indiquemos que se van a utilizar en nuestro site deberan definir los métodos correspondientes a los verbos que queramos implementar (GET, POST...).
class index:
def GET(self):
return "Hello, world!"
=== Ejecución del servidor ===
Para iniciar el motor de web.py deberemos ejecutar ''app.run()'':
if __name__ == "__main__": app.run()
Si ejecutamos el código así, tal cual (''$ python code.py''), podremos indicar al entorno que escuche por un puerto concreto (''$ python code.py 2727'') y\o en una dirección concreta (''$ python code.py 127.0.0.1 2727'', si no lo hiciesemos escucharía por el puerto 8080.
==== Tratar la entreda ====
=== Recoger datos del POST ===
* ''web.input()'' devuelve los datos pasados por POST.
web.input() # Devuelve lista de parámetros.
==== Tratar la salida ====
=== Cambiar el content-type ===
class index:
def GET(self, code):
web.header('Content-Type', 'text/xml')
return render.index(code)
Puedes ver distintos content-type [[code:concepts#protocolo_http|aquí]].
=== Devolver un fichero ===
def GET(self, code):
...
web.header('Content-Type', 'text/csv')
web.header('Content-Disposition', 'attachment;filename=myfilename.csv')
return value
==== Formularios ====
==== Sesiones y autentificación ====
[[http://webpy.org/docs/0.3/sessions]]
==== Contenido estático ====
=== Carpeta static ===
Podemos agregar una carpeta static en la ruta de la aplicación, esta contendrá los documentos que no cambian. Por ejemplo ''http://localhost/static/logo.png'' enviaría la imágen ''./static/logo.png''. \\
Una carpeta mapeada a partir de la directiva ''Alias'' de Apache también serviría.
=== A partir de código ===
import os
import web
urls = (
'/images/(.*)', 'images' #this is where the image folder is located....
)
class images:
def GET(self,name):
ext = name.split(".")[-1] # Gather extension
cType = {
"png":"images/png",
"jpg":"image/jpeg",
"gif":"image/gif",
"ico":"image/x-icon" }
if name in os.listdir('images'): # Security
web.header("Content-Type", cType[ext]) # Set the Header
return open('images/%s'%name,"rb").read() # Notice 'rb' for reading images
else:
raise web.notfound()
==== Subir ficheros ====
===== Avanzado =====
==== Mimerender ====
* [[http://code.google.com/p/mimerender|Página web]]
* {{fw:others:mimerender-0.2.2.tar.gz|}}
Es una librería que parsea el retorno de una URL en el formato indicado.
=== Código de ejemplo ===
import web
import json
from mimerender import mimerender
render_xml = lambda message: '%s'%message
render_json = lambda **args: json.dumps(args)
render_html = lambda message: '%s'%message
render_txt = lambda message: message
urls = (
'/(.*)', 'greet'
)
app = web.application(urls, globals())
class greet:
@mimerender(
default = 'html',
html = render_html,
xml = render_xml,
json = render_json,
txt = render_txt
)
def GET(self, name):
if not name:
name = 'world'
return {'message': 'Hello, ' + name + '!'}
if __name__ == "__main__":
app.run()
=== Llamadas y retorno ===
$ curl -H "Accept: application/html" localhost:8080/x
Hello, x!
$ curl -H "Accept: application/xml" localhost:8080/x
Hello, x!
$ curl -H "Accept: application/json" localhost:8080/x
{'message':'Hello, x!'}
$ curl -H "Accept: text/plain" localhost:8080/x
Hello, x!
===== Notas =====
==== Cómo... ====
=== ... Usar Cheetah? ===
=== ... Usar Elixir? ===
Para utilizar [[fw:elixir|Elixir]] en un código que utilice web.py simplemente has de lanzar un ''setup_all()'' al principio, justo después de haber importado el código del modelo.
=== ... Usarlo en un servidor de producción? ===
Tipo Apache o Lighttpd. \\
==== Notas ====
=== Aplicaciones de ejemplo ===
* {{fw:others:webpy:andreisavu-music-share-09b9eec.zip|Aplicación para compartir .mp3}}
=== Ideas para la creación de un proceso en background ===
:!: Falta probar en producción
#!/usr/bin/python
# -*- coding: utf-8 *-*
import web
import json
from mimerender import mimerender
from multiprocessing import Process
render_xml = lambda message: '%s'%message
render_json = lambda **args: json.dumps(args)
render_html = lambda message: '%s'%message
render_txt = lambda message: message
urls = (
'/(.*)', 'greet'
)
app = web.application(urls, globals())
p = Process()
class greet:
@mimerender(
default = 'html',
html = render_html,
xml = render_xml,
json = render_json,
txt = render_txt
)
def GET(self, name):
global p
p = Process(target = self.test)
p.start()
if not name:
name = 'world'
return {'message': 'Hello, ' + name + '!'}
def test (self):
import os
print 'entra!!!'
os.system('ls -laR / > /home/alfred/Desktop/test.txt')
if __name__ == "__main__":
app.run()
p.join()