Estructura y ciclo de vida de la aplicación¶
Flask hace que sea bastante fácil escribir una aplicación web. Pero hay bastantes partes diferentes en una aplicación y en cada petición que maneja. Saber lo que ocurre durante la configuración de la aplicación, el servicio y el manejo de las peticiones te ayudará a saber qué es posible en Flask y cómo estructurar tu aplicación.
Application Setup¶
El primer paso para crear una aplicación Flask es crear el objeto aplicación. Cada aplicación Flask es una instancia de la clase Flask, que recoge toda la configuración, extensiones y vistas.
from flask import Flask
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY="dev",
)
app.config.from_prefixed_env()
@app.route("/")
def index():
return "Hello, World!"
Esto se conoce como la «fase de configuración de la aplicación», es el código que escribes que está fuera de cualquier función de vista u otros manejadores. Puede estar dividido entre diferentes módulos y subpaquetes, pero todo el código que quieras que forme parte de tu aplicación debe ser importado para que pueda ser registrado.
Toda la configuración de la aplicación debe ser completada antes de empezar a servir su aplicación y manejar las peticiones. Esto se debe a que los servidores WSGI dividen el trabajo entre múltiples workers, o pueden ser distribuidos a través de múltiples máquinas. Si la configuración cambia en un trabajador, no hay forma de que Flask asegure la consistencia entre otros trabajadores.
Flask intenta ayudar a los desarrolladores a detectar algunos de estos problemas de ordenación de la configuración mostrando un error si se llaman métodos relacionados con la configuración después de gestionar las peticiones. En ese caso verás este error:
El método de configuración “route” ya no puede ser llamado en la aplicación. Ya ha gestionado su primera petición, cualquier cambio no se aplicará de forma consistente. Asegúrese de que todas las importaciones, decoradores, funciones, etc. necesarios para configurar la aplicación se realizan antes de ejecutarla.
Sin embargo, no es posible que Flask detecte todos los casos de configuración fuera de orden. En general, no hagas nada para modificar el objeto Flask app y los objetos Blueprint desde dentro de las funciones de vista que se ejecutan durante las peticiones. Esto incluye:
Añadir rutas, funciones de vista y otros gestores de peticiones con
@app.route,@app.errorhandler,@app.before_request, etc.Registro de blueprints.
Cargando configuración con
app.config.Configurar el entorno de plantillas Jinja con
app.jinja_env.Establecer una interfaz de sesión, en lugar de la cookie por defecto itsdangerous.
Establecer un proveedor JSON con
app.json, en lugar del proveedor por defecto.Creación e inicialización de extensiones Flask.
Servir la aplicación¶
Flask es un framework de aplicaciones WSGI. La otra mitad de WSGI es el servidor WSGI. Durante el desarrollo, Flask, a través de Werkzeug, proporciona un servidor WSGI de desarrollo con el comando CLI flask run. Cuando hayas terminado con el desarrollo, utiliza un servidor de producción para servir tu aplicación, ver Despliegue a producción.
Independientemente del servidor que utilices, seguirá la especificación PEP 3333 WSGI. Se le dirá al servidor WSGI cómo acceder a tu objeto de aplicación Flask, que es la aplicación WSGI. Entonces empezará a escuchar peticiones HTTP, traducirá los datos de la petición a un entorno WSGI, y llamará a la aplicación WSGI con esos datos. La aplicación WSGI devolverá los datos traducidos en una respuesta HTTP.
El navegador u otro cliente realiza una petición HTTP.
El servidor WSGI recibe la petición.
El servidor WSGI convierte los datos HTTP en WSGI
environdict.El servidor WSGI llama a la aplicación WSGI con el
environ.Flask, la aplicación WSGI, hace todo su procesamiento interno para enrutar la petición a una función de vista, manejar errores, etc.
Flask traduce el retorno de la función View en datos de respuesta WSGI y los pasa al servidor WSGI.
El servidor WSGI crea y envía una respuesta HTTP.
El cliente recibe la respuesta HTTP.
Middleware¶
La aplicación WSGI anterior es un callable que se comporta de una determinada manera. Middleware es una aplicación WSGI que envuelve a otra aplicación WSGI. Es un concepto similar a los decoradores de Python. El middleware más externo será llamado por el servidor. Puede modificar los datos que se le pasan, luego llamar a la aplicación WSGI (o más middleware) que envuelve, y así sucesivamente. Y puede tomar el valor de retorno de esa llamada y modificarlo aún más.
Desde la perspectiva del servidor WSGI, hay una aplicación WSGI, la que llama directamente. Normalmente, Flask es la aplicación «real» al final de la cadena de middleware. Pero incluso Flask puede llamar a otras aplicaciones WSGI, aunque ese es un caso de uso avanzado y poco común.
Un middleware común que verás usado con Flask es ProxyFix de Werkzeug, que modifica la petición para que parezca que viene directamente de un cliente aunque haya pasado por proxies HTTP en el camino. Hay otros middleware que pueden manejar el servicio de archivos estáticos, autenticación, etc.
Cómo se gestiona una solicitud¶
Para nosotros, la parte interesante de los pasos anteriores es cuando Flask es llamado por el servidor WSGI (o middleware). En ese momento, va a hacer mucho para manejar la solicitud y generar la respuesta. En el más básico, que coincidirá con la URL a una función de vista, llame a la función de vista, y pasar el valor de retorno al servidor. Pero hay muchas más partes que puedes usar para personalizar su comportamiento.
El servidor WSGI llama al objeto Flask, que llama a
Flask.wsgi_app().Se crea un objeto
RequestContext. Esto convierte el dict WSGIenvironen un objetoRequest. También crea un objetoAppContext.El contexto de aplicación es empujado, lo que hace que
aplicación_actualygestén disponibles.Se envía la señal
appcontext_pushed.El contexto de petición es empujado, lo que hace que
requestysessionestén disponibles.Se abre la sesión, cargando cualquier dato de sesión existente usando el
session_interfacede la aplicación, una instancia deSessionInterface.La URL se compara con las reglas de URL registradas con el decorador
route()durante la configuración de la aplicación. Si no hay coincidencia, el error - normalmente un 404, 405, o redirección - se almacena para ser manejado más tarde.Se envía la señal
request_started.Se llama a cualquier función decorada con
url_value_preprocessor().Se llama a cualquier función decorada con
before_request(). Si alguna de estas funciones devuelve un valor se trata como la respuesta inmediatamente.Si la URL no coincidía con una ruta hace unos pasos, ese error se produce ahora.
Se llama a la función de vista decorada
route()asociada a la URL coincidente y devuelve un valor que se utilizará como respuesta.Si en alguno de los pasos anteriores se ha producido una excepción y existe una función decorada con
errorhandler()que coincida con la clase de excepción o el código de error HTTP, se llama a esta función para que gestione el error y devuelva una respuesta.Sea lo que sea lo que devuelva un valor de respuesta - una función anterior a la petición, la vista, o un manejador de errores, ese valor se convierte en un objeto
Response.Cualquier función decorada con
after_this_request()es llamada y luego borrada.Se llama a cualquier función decorada con
after_request()que pueda modificar el objeto respuesta.La sesión se guarda, persistiendo cualquier dato de sesión modificado utilizando el
session_interfacede la aplicación.Se envía la señal
request_finished.Si algún paso hasta el momento planteó una excepción, y no fue manejado por una función manejadora de errores, se maneja ahora. Las excepciones HTTP se tratan como respuestas con su código de estado correspondiente, otras excepciones se convierten en una respuesta genérica 500. Se envía la señal
got_request_exception.El estado, las cabeceras y el cuerpo del objeto de respuesta se devuelven al servidor WSGI.
Se llama a cualquier función decorada con
teardown_request().Se envía la señal
request_tearing_down.El contexto de petición ha sido eliminado,
requestysessionya no están disponibles.Se llama a cualquier función decorada con
teardown_appcontext().Se envía la señal
appcontext_tearing_down.El contexto de la aplicación ha desaparecido,
current_appygya no están disponibles.Se envía la señal
appcontext_popped.
Hay incluso más decoradores y puntos de personalización que estos, pero que no forman parte de todos los ciclos de vida de las peticiones. Son más específicos para ciertas cosas que podrías usar durante una petición, como plantillas, construcción de URLs, o manejo de datos JSON. Consulta el resto de esta documentación, así como API para profundizar en el tema.