Quickstart

¿Ansioso por empezar? Esta página ofrece una buena introducción a Flask. Sigue Instalación para configurar un proyecto e instalar Flask primero.

Una aplicación sencilla

Una aplicación Flask sencilla se parece a esto:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

¿Y qué hacía ese código?

  1. Primero importamos la clase Flask. Una instancia de esta clase será nuestra aplicación WSGI.

  2. A continuación creamos una instancia de esta clase. El primer argumento es el nombre del módulo o paquete de la aplicación. __name__ es un atajo conveniente para esto que es apropiado para la mayoría de los casos. Esto es necesario para que Flask sepa dónde buscar recursos como plantillas y archivos estáticos.

  3. A continuación, utilizamos el decorador route() para indicar a Flask qué URL debe activar nuestra función.

  4. La función devuelve el mensaje que queremos mostrar en el navegador del usuario. El tipo de contenido por defecto es HTML, por lo que el HTML de la cadena será renderizado por el navegador.

Guárdalo como hello.py o algo similar. Asegúrate de no llamar a tu aplicación flask.py porque esto entraría en conflicto con el propio Flask.

To run the application, use the flask command or python -m flask. You need to tell the Flask where your application is with the --app option.

$ flask --app hello run
 * Serving Flask app 'hello'
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)

Comportamiento del descubrimiento de aplicaciones

Como atajo, si el archivo se llama app.py o wsgi.py, no tienes que usar --app. Consulta Interfaz de línea de comandos para más detalles.

Esto lanza un servidor incorporado muy simple, que es lo suficientemente bueno para las pruebas, pero probablemente no es lo que quieres usar en producción. Para ver las opciones de despliegue vea Despliegue en producción.

Ahora dirígete a http://127.0.0.1:5000/, y deberías ver tu saludo de hola mundo.

Si otro programa ya está usando el puerto 5000, verás OSError: [Errno 98] o OSError: [WinError 10013] cuando el servidor intente iniciarse. Ver Dirección ya utilizada para saber cómo manejar esto.

Servidor visible desde el exterior

Si ejecutas el servidor notarás que el servidor sólo es accesible desde tu propio ordenador, no desde ningún otro de la red. Este es el valor por defecto porque en el modo de depuración un usuario de la aplicación puede ejecutar código Python arbitrario en su ordenador.

Si tienes el depurador desactivado o confías en los usuarios de tu red, puedes hacer que el servidor esté disponible públicamente simplemente añadiendo --host=0.0.0 a la línea de comandos:

$ flask run --host=0.0.0.0

Esto le dice a su sistema operativo que escuche en todas las IPs públicas.

Modo de depuración

El comando flask run puede hacer algo más que iniciar el servidor de desarrollo. Al activar el modo de depuración, el servidor se recargará automáticamente si el código cambia, y mostrará un depurador interactivo en el navegador si se produce un error durante una solicitud.

El depurador interactivo en acción.

Advertencia

El depurador permite ejecutar código Python arbitrario desde el navegador. Está protegido por un pin, pero sigue representando un riesgo de seguridad importante. No ejecute el servidor de desarrollo o el depurador en un entorno de producción.

To enable debug mode, use the --debug option.

$ flask --app hello run --debug
 * Serving Flask app 'hello'
 * Debug mode: on
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: nnn-nnn-nnn

Vea también:

Escape de HTML

Cuando se devuelve HTML (el tipo de respuesta por defecto en Flask), cualquier valor proporcionado por el usuario en la salida debe ser escapado para protegerlo de ataques de inyección. Las plantillas HTML renderizadas con Jinja, introducidas más tarde, harán esto automáticamente.

escape(), que se muestra aquí, puede utilizarse manualmente. Se omite en la mayoría de los ejemplos por razones de brevedad, pero siempre debes ser consciente de cómo estás utilizando datos no confiables.

from markupsafe import escape

@app.route("/<name>")
def hello(name):
    return f"Hello, {escape(name)}!"

Si un usuario logró enviar el nombre <script>alert("bad")</script>, el escape hace que se renderice como texto, en lugar de ejecutar el script en el navegador del usuario.

La variable <name> en la ruta captura un valor de la URL y lo pasa a la función de la vista. Estas reglas de las variables se explican a continuación.

Enrutamiento

Las aplicaciones web modernas utilizan URLs significativas para ayudar a los usuarios. Es más probable que a los usuarios les guste una página y vuelvan si la página utiliza una URL significativa que puedan recordar y utilizar para visitar directamente una página.

Utilice el decorador route() para vincular una función a una URL.

@app.route('/')
def index():
    return 'Index Page'

@app.route('/hello')
def hello():
    return 'Hello, World'

Puedes hacer más. Puedes hacer que partes de la URL sean dinámicas y adjuntar múltiples reglas a una función.

Normas variables

Puedes añadir secciones variables a una URL marcando las secciones con <nombre_de_variable>. Su función recibe entonces el <nombre_de_variable> como argumento de palabra clave. Opcionalmente, puedes usar un convertidor para especificar el tipo de argumento como <converter:nombre_de_variable>.

from markupsafe import escape

@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return f'User {escape(username)}'

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return f'Post {post_id}'

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    # show the subpath after /path/
    return f'Subpath {escape(subpath)}'

Tipos de convertidores:

string

(Por defecto) acepta cualquier texto sin barra

int

acepta números enteros positivos

float

acepta valores positivos en coma flotante

path

como string pero también acepta barras inclinadas

uuid

acepta cadenas (string) UUID

URLs únicas / Comportamiento de la redirección

Las dos reglas siguientes difieren en el uso de la barra diagonal final:

@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

La URL canónica del endpoint projects tiene una barra al final. Es similar a una carpeta en un sistema de archivos. Si accedes a la URL sin la barra final (/projects), Flask te redirige a la URL canónica con la barra final (/projects/).

La URL canónica para el endpoint about no tiene una barra al final. Es similar a la ruta de un archivo. El acceso a la URL con una barra al final (/about/) produce un error 404 «Not Found». Esto ayuda a mantener las URLs únicas para estos recursos, lo que ayuda a los motores de búsqueda a evitar indexar la misma página dos veces.

Construcción de URLs

Para construir una URL a una función específica, utilice la función url_for(). Acepta el nombre de la función como primer argumento y cualquier número de argumentos de palabra clave, cada uno correspondiente a una parte variable de la regla de la URL. Las partes variables desconocidas se añaden a la URL como parámetros de consulta.

¿Por qué querrías construir URLs usando la función de inversión de URLs url_for() en lugar de codificarlas en tus plantillas?

  1. La inversión suele ser más descriptiva que la codificación de las URL.

  2. Puedes cambiar tus URLs de una sola vez en lugar de tener que recordar cambiar manualmente las URLs codificadas.

  3. La construcción de URLs maneja el escape de caracteres especiales de forma transparente.

  4. Las rutas generadas son siempre absolutas, evitando el comportamiento inesperado de las rutas relativas en los navegadores.

  5. Si tu aplicación está situada fuera de la raíz de la URL, por ejemplo, en /mi_aplicacion en lugar de /, url_for() lo gestiona adecuadamente.

Por ejemplo, aquí usamos el método test_request_context() para probar url_for(). test_request_context() le dice a Flask que se comporte como si estuviera manejando una petición incluso mientras usamos un shell de Python. Ver Contextos locales.

from flask import url_for

@app.route('/')
def index():
    return 'index'

@app.route('/login')
def login():
    return 'login'

@app.route('/user/<username>')
def profile(username):
    return f'{username}\'s profile'

with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='John Doe'))
/
/login
/login?next=/
/user/John%20Doe

Métodos HTTP

Las aplicaciones web utilizan diferentes métodos HTTP para acceder a las URL. Debes familiarizarte con los métodos HTTP mientras trabajas con Flask. Por defecto, una ruta sólo responde a peticiones GET. Puedes utilizar el argumento methods del decorador route() para manejar diferentes métodos HTTP:

from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return do_the_login()
    else:
        return show_the_login_form()

El ejemplo anterior mantiene todos los métodos para la ruta dentro de una función, lo que puede ser útil si cada parte utiliza algunos datos comunes.

También puedes separar las vistas para diferentes métodos en diferentes funciones. Flask proporciona un atajo para decorar dichas rutas con get(), post(), etc. para cada método HTTP común.

@app.get('/login')
def login_get():
    return show_the_login_form()

@app.post('/login')
def login_post():
    return do_the_login()

Si GET está presente, Flask añade automáticamente soporte para el método HEAD y maneja las peticiones HEAD de acuerdo con el HTTP RFC. Del mismo modo, OPTIONS se implementa automáticamente por ti.

Archivos estáticos

Las aplicaciones web dinámicas también necesitan archivos estáticos. Por lo general, de ahí vienen los archivos CSS y JavaScript. Idealmente tu servidor web está configurado para servirlos por ti, pero durante el desarrollo Flask puede hacerlo también. Simplemente crea una carpeta llamada static en tu paquete o junto a tu módulo y estará disponible en /static en la aplicación.

Para generar URLs para archivos estáticos, utilice el nombre de endpoint especial 'static':

url_for('static', filename='style.css')

El archivo debe ser almacenado en el sistema de archivos como static/style.css.

Plantillas de renderizado

Generar HTML desde Python no es divertido, y en realidad es bastante engorroso porque tienes que hacer el escape de HTML por tu cuenta para mantener la aplicación segura. Por eso Flask configura el motor de plantillas Jinja2 por ti automáticamente.

Templates can be used to generate any type of text file. For web applications, you’ll primarily be generating HTML pages, but you can also generate markdown, plain text for emails, and anything else.

For a reference to HTML, CSS, and other web APIs, use the MDN Web Docs.

Para renderizar una plantilla puedes utilizar el método render_template(). Todo lo que tienes que hacer es proporcionar el nombre de la plantilla y las variables que quieres pasar al motor de plantillas como argumentos de palabra clave. Este es un ejemplo sencillo de cómo renderizar una plantilla:

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Flask buscará las plantillas en la carpeta templates. Así que si su aplicación es un módulo, esta carpeta está al lado de ese módulo, si es un paquete está realmente dentro de su paquete:

Caso 1: Un módulo:

/application.py
/templates
    /hello.html

Caso 2: Un paquete:

/application
    /__init__.py
    /templates
        /hello.html

Para las plantillas puedes utilizar toda la potencia de las plantillas de Jinja2. Dirígete a la documentación oficial de Jinja2 Template Documentation para más información.

Aquí tiene una plantilla de ejemplo:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

Dentro de las plantillas también tienes acceso a los objetos config, request, session y g 1 así como a las funciones url_for() y get_flashed_messages().

Las plantillas son especialmente útiles si se utiliza la herencia. Si quieres saber cómo funciona, consulta Herencia de plantillas. Básicamente la herencia de plantillas permite mantener ciertos elementos en cada página (como la cabecera, la navegación y el pie de página).

El escape automático está activado, así que si name contiene HTML será escapado automáticamente. Si puedes confiar en una variable y sabes que será HTML seguro (por ejemplo, porque proviene de un módulo que convierte el marcado wiki en HTML) puedes marcarla como segura usando la clase Markup o usando el filtro |safe en la plantilla. Dirígete a la documentación de Jinja 2 para ver más ejemplos.

He aquí una introducción básica al funcionamiento de la clase Markup:

>>> from markupsafe import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup('<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup('&lt;blink&gt;hacker&lt;/blink&gt;')
>>> Markup('<em>Marked up</em> &raquo; HTML').striptags()
'Marked up » HTML'
Changelog

Distinto en la versión 0.5: El autoescapado ya no está activado para todas las plantillas. Las siguientes extensiones de plantillas activan el autoescapado: .html, .htm, .xml, .xhtml. Las plantillas cargadas desde una cadena tendrán el autoescapado desactivado.

1

¿No sabes qué es ese objeto g? Es algo en lo que puedes almacenar información para tus propias necesidades. Consulta la documentación de flask.g y Uso de SQLite 3 con Flask.

Acceso a los datos de la solicitud

Para las aplicaciones web es crucial reaccionar a los datos que un cliente envía al servidor. En Flask esta información la proporciona el objeto global request. Si tienes algo de experiencia con Python te preguntarás cómo puede ser global ese objeto y cómo consigue Flask seguir siendo threadsafe. La respuesta es el contexto local:

Contextos locales

Información privilegiada

Si quieres entender cómo funciona esto y cómo puedes implementar pruebas con locales de contexto, lee esta sección, de lo contrario sólo sáltatela.

Algunos objetos en Flask son objetos globales, pero no del tipo habitual. Estos objetos son en realidad proxies de objetos que son locales a un contexto específico. Menudo trabalenguas. Pero en realidad es bastante fácil de entender.

Imagina que el contexto es el hilo de manejo. Llega una petición y el servidor web decide generar un nuevo hilo (o algo más, el objeto subyacente es capaz de tratar con sistemas de concurrencia distintos de los hilos). Cuando Flask inicia su gestión interna de peticiones, averigua que el hilo actual es el contexto activo y vincula la aplicación actual y los entornos WSGI a ese contexto (hilo). Lo hace de una manera inteligente para que una aplicación pueda invocar a otra sin romperse.

¿Qué significa esto para ti? Básicamente puedes ignorar por completo que esto es así a menos que estés haciendo algo como pruebas unitarias. Te darás cuenta de que el código que depende de un objeto request se romperá de repente porque no hay un objeto request. La solución es crear un objeto request y vincularlo al contexto. La solución más fácil para las pruebas unitarias es utilizar el gestor de contexto test_request_context(). En combinación con la sentencia with vinculará una petición de prueba para que puedas interactuar con ella. Aquí hay un ejemplo:

from flask import request

with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == '/hello'
    assert request.method == 'POST'

La otra posibilidad es pasar todo un entorno WSGI al método request_context():

with app.request_context(environ):
    assert request.method == 'POST'

El objeto Request

El objeto request está documentado en la sección API y no lo cubriremos aquí en detalle (ver Request). A continuación, un amplio resumen de algunas de las operaciones más comunes. En primer lugar tienes que importarlo desde el módulo flask:

from flask import request

El método de solicitud actual está disponible utilizando el atributo method. Para acceder a los datos del formulario (datos transmitidos en una petición POST o PUT) se puede utilizar el atributo form. He aquí un ejemplo completo de los dos atributos mencionados anteriormente:

@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('login.html', error=error)

¿Qué ocurre si la clave no existe en el atributo form? En ese caso se produce un KeyError especial. Puedes cogerlo como un KeyError estándar, pero si no lo haces, se muestra una página de error HTTP 400 Bad Request en su lugar. Así que para muchas situaciones no tienes que lidiar con ese problema.

Para acceder a los parámetros enviados en la URL (?key=value) puede utilizar el atributo args:

searchword = request.args.get('key', '')

Recomendamos acceder a los parámetros de la URL con get o capturando el KeyError porque los usuarios podrían cambiar la URL y presentarles una página 400 de solicitud incorrecta en ese caso no es amigable para el usuario.

Para una lista completa de métodos y atributos del objeto request, dirígete a la documentación de Request.

Carga de archivos

Puedes manejar los archivos subidos con Flask fácilmente. Sólo asegúrese de no olvidar establecer el atributo enctype="multipart/form-data" en su formulario HTML, de lo contrario el navegador no transmitirá sus archivos en absoluto.

Los archivos subidos se almacenan en la memoria o en una ubicación temporal en el sistema de archivos. Puede acceder a esos archivos mirando el atributo files del objeto request. Cada archivo subido se almacena en ese diccionario. Se comporta como un objeto file estándar de Python, pero también tiene un método save() que permite almacenar ese fichero en el sistema de ficheros del servidor. Aquí hay un ejemplo sencillo que muestra cómo funciona:

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

Si quieres saber cómo se nombró el archivo en el cliente antes de subirlo a tu aplicación, puedes acceder al atributo filename. Sin embargo, ten en cuenta que este valor puede ser falsificado, así que nunca confíes en él. Si quieres utilizar el nombre de archivo del cliente para almacenar el archivo en el servidor, pásalo a través de la función secure_filename() que te proporciona Werkzeug:

from werkzeug.utils import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['the_file']
        file.save(f"/var/www/uploads/{secure_filename(file.filename)}")
    ...

Para ver algunos ejemplos mejores, consulte Carga de archivos.

Cookies

Para acceder a las cookies se puede utilizar el atributo cookies. Para establecer las cookies se puede utilizar el método set_cookie de los objetos de respuesta. El atributo cookies de los objetos request es un diccionario con todas las cookies que transmite el cliente. Si quieres utilizar sesiones, no utilices las cookies directamente, sino que utiliza la Sesiones de Flask que añade algo de seguridad sobre las cookies por ti.

Leyendo cookies:

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.

Almacenando cookies:

from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

Tenga en cuenta que las cookies se establecen en los objetos de respuesta. Como normalmente sólo devuelves cadenas desde las funciones de la vista, Flask las convertirá en objetos de respuesta por ti. Si quieres hacerlo explícitamente puedes usar la función make_response() y luego modificarla.

A veces puede querer establecer una cookie en un punto en el que el objeto de respuesta aún no existe. Esto es posible utilizando el patrón Callbacks en diferido.

Para ello, consulte también Acerca de las respuestas.

Redirecciones y errores

Para redirigir a un usuario a otro endpoint, utilice la función redirect(); para abortar una solicitud antes de tiempo con un código de error, utilice la función abort():

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

Este es un ejemplo bastante inútil porque un usuario será redirigido desde el índice a una página a la que no puede acceder (401 significa acceso denegado) pero muestra cómo funciona.

Por defecto se muestra una página de error en blanco y negro para cada código de error. Si quieres personalizar la página de error, puedes usar el decorador errorhandler():

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

Observa el 404 después de la llamada render_template(). Esto le dice a Flask que el código de estado de esa página debe ser 404 que significa no encontrado. Por defecto se asume 200 que se traduce en: todo ha ido bien.

Consulte Manejo de los errores de la aplicación para más detalles.

Acerca de las respuestas

El valor de retorno de una función de la vista se convierte automáticamente en un objeto de respuesta. Si el valor devuelto es una cadena, se convierte en un objeto de respuesta con la cadena como cuerpo de la respuesta, un código de estado 200 OK y un mimetype:text/html. Si el valor de retorno es un dict o una lista, se llama a jsonify() para producir una respuesta. La lógica que aplica Flask para convertir los valores de retorno en objetos de respuesta es la siguiente:

  1. Si se devuelve un objeto response del tipo correcto se devuelve directamente desde la vista.

  2. Si es una cadena, se crea un objeto response con esos datos y los parámetros por defecto.

  3. Si se trata de un iterador o generador que devuelve cadenas o bytes, se trata como una respuesta de flujo.

  4. Si es un dict o una lista, se crea un objeto de respuesta utilizando jsonify().

  5. Si se devuelve una tupla, los elementos de la tupla pueden proporcionar información extra. Estas tuplas tienen que tener la forma (response, state), (response, headers), o (response, state, headers). El valor status anulará el código de state y headers puede ser una lista o diccionario de valores de cabecera adicionales.

  6. Si nada de esto funciona, Flask asumirá que el valor de retorno es una aplicación WSGI válida y lo convertirá en un objeto response.

Si quieres obtener el objeto respuesta resultante dentro de la vista puedes utilizar la función make_response().

Imagina que tienes una vista como esta:

from flask import render_template

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'), 404

Sólo tienes que envolver la expresión de retorno con make_response() y obtener el objeto de respuesta para modificarlo, luego devolverlo:

from flask import make_response

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

APIs con JSON

Un formato de respuesta común al escribir una API es JSON. Es fácil empezar a escribir una API de este tipo con Flask. Si devuelves un dict o list desde una vista, se convertirá en una respuesta JSON.

@app.route("/me")
def me_api():
    user = get_current_user()
    return {
        "username": user.username,
        "theme": user.theme,
        "image": url_for("user_image", filename=user.image),
    }

@app.route("/users")
def users_api():
    users = get_all_users()
    return [user.to_json() for user in users]

Este es un atajo para pasar los datos a la función jsonify(), que serializará cualquier tipo de datos JSON soportado. Esto significa que todos los datos en el dict o la lista deben ser JSON serializable.

Para los tipos complejos, como los modelos de bases de datos, querrás utilizar una biblioteca de serialización para convertir los datos en tipos JSON válidos primero. Hay muchas bibliotecas de serialización y extensiones de la API de Flask mantenidas por la comunidad que soportan aplicaciones más complejas.

Sesiones

Además del objeto request, existe un segundo objeto llamado session que permite almacenar información específica de un usuario de una solicitud a otra. Esto se implementa encima de las cookies para usted y firma las cookies criptográficamente. Lo que esto significa es que el usuario podría mirar el contenido de su cookie pero no modificarlo, a menos que conozca la clave secreta utilizada para la firma.

Para utilizar las sesiones hay que establecer una clave secreta. Así es como funcionan las sesiones:

from flask import session

# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    if 'username' in session:
        return f'Logged in as {session["username"]}'
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

Cómo generar buenas claves secretas

Una clave secreta debe ser lo más aleatoria posible. Su sistema operativo tiene formas de generar datos bastante aleatorios basados en un generador aleatorio criptográfico. Utilice el siguiente comando para generar rápidamente un valor para Flask.secret_key (o SECRET_KEY):

$ python -c 'import secrets; print(secrets.token_hex())'
'192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'

Una nota sobre las sesiones basadas en cookies: Flask tomará los valores que pongas en el objeto de sesión y los serializará en una cookie. Si encuentra que algunos valores no persisten a través de las solicitudes, las cookies están efectivamente habilitadas, y no está recibiendo un mensaje de error claro, compruebe el tamaño de la cookie en las respuestas de su página en comparación con el tamaño soportado por los navegadores web.

Además de las sesiones por defecto basadas en el lado del cliente, si quieres manejar las sesiones en el lado del servidor, hay varias extensiones de Flask que soportanhis.

Mensajes Flash

Las buenas aplicaciones e interfaces de usuario se basan en la retroalimentación. Si el usuario no recibe suficiente retroalimentación, probablemente terminará odiando la aplicación. Flask proporciona una forma muy sencilla de dar retroalimentación a un usuario con el sistema de parpadeo. El sistema de parpadeo básicamente permite grabar un mensaje al final de una solicitud y acceder a él en la siguiente (y sólo la siguiente) solicitud. Esto se suele combinar con una plantilla de diseño para exponer el mensaje.

Para flashear un mensaje utilice el método flash(), para obtener los mensajes puede utilizar get_flashed_messages() que también está disponible en las plantillas. Ver Mensaje Flash para un ejemplo completo.

Registro

Changelog

Nuevo en la versión 0.3.

A veces puedes encontrarte en una situación en la que tratas con datos que deberían ser correctos, pero que en realidad no lo son. Por ejemplo, puedes tener algún código del lado del cliente que envíe una petición HTTP al servidor pero que esté obviamente malformada. Esto puede ser causado por un usuario que manipula los datos, o por un fallo en el código del cliente. La mayoría de las veces está bien responder con 400 Bad Request en esa situación, pero a veces eso no es suficiente y el código tiene que seguir trabajando.

Puede que aún así quieras registrar que ha ocurrido algo sospechoso. Aquí es donde los registradores son útiles. A partir de la versión 0.3 de Flask, se ha preconfigurado un registrador para su uso.

Aquí hay algunos ejemplos de llamadas de registro:

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

El logger adjunto es un Logger estándar de registro, así que dirígete a la documentación oficial de logging para más información.

Ver Manejo de los errores de la aplicación.

Hooking en el WSGI middleware

Para añadir WSGI middleware a tu aplicación Flask, envuelve el atributo wsgi_app de la aplicación. Por ejemplo, para aplicar el middleware ProxyFix de Werkzeug para ejecutar detrás de Nginx:

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

Envolver app.wsgi_app en lugar de app significa que app sigue apuntando a tu aplicación Flask, no al middleware, por lo que puedes seguir utilizando y configurando app directamente.

Uso de las extensiones de Flask

Las extensiones son paquetes que ayudan a realizar tareas comunes. Por ejemplo, Flask-SQLAlchemy proporciona soporte para SQLAlchemy que lo hace simple y fácil de usar con Flask.

Para más información sobre las extensiones de Flask, véase Extensiones.

Despliegue en un servidor web

¿Listo para desplegar tu nueva aplicación Flask? Consulte Despliegue en producción.