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