Qué es el objeto g en Flask y cómo usarlo con ejemplos prácticos

El objeto g en Flask es una herramienta poderosa y útil que permite almacenar datos temporales durante el ciclo de vida de una solicitud HTTP.

g es un objeto especial proporcionado por Flask cuyo propósito principal es actuar como un almacén temporal de datos. Esto facilita compartir información entre diferentes partes de tu aplicación durante una solicitud, sin necesidad de pasar datos manualmente.

python
# Importando Flask y el objeto g
from flask import Flask, g

Principales características de g:

  Principales características de g

  • Único por solicitud: Cada solicitud tiene su propia instancia de g, lo que asegura que los datos no se compartan entre solicitudes concurrentes.
  • Temporal: Los datos almacenados en g desaparecen automáticamente una vez que la solicitud termina.
  • Flexible: Puedes almacenar cualquier tipo de dato en g, desde cadenas y listas hasta objetos complejos.

Uso típico de g:

  Importante

El objeto g es ideal para almacenar información que necesitas reutilizar durante una solicitud, como:

  • Información del usuario autenticado (nombre, rol, etc.).
  • Configuraciones o resultados de cálculos temporales.
  • Conexiones a la base de datos u objetos de sesión.

Ejemplo para explorar g:

Si imprimes el tipo de g, verás algo como esto:

python
# Importando Flask y el objeto g
from flask import Flask, g

app = Flask(__name__)

@app.route('/')
def home():
  g.message = "Hola, soy g"
  print(type(g))

  # Esto imprimirá:
  # <class 'werkzeug.local.LocalProxy'>
  return g.message

if __name__ == '__main__':
  app.run(debug=True, port=5000)

1. Ejemplo práctico: Middleware de autenticación

Puedes usar g para almacenar datos de autenticación y utilizarlos en diferentes partes de tu aplicación. A continuación, un ejemplo básico para mostrar cómo funciona el objeto g:

python
from flask import Flask, g, request

app = Flask(__name__)

@app.before_request
def before_request():
  # Simulamos cargar un usuario
  g.user = {'name': 'Urian', 'role': 'admin'}

@app.route('/')
def home():
  return f"Bienvenido {g.user['name']}! Tu rol es: {g.user['role']}"

if __name__ == '__main__':
  app.run(debug=True, port=5000)
  Explicación

  • En @app.before_request, cargamos información de un usuario ficticio y la almacenamos en g.user.
  • En la ruta /, accedemos a los datos de g sin necesidad de pasarlos como argumentos.

2. Contador de visitas utilizando el objeto g en Flask

Cada vez que alguien acceda a la ruta principal (/), se incrementará el contador de visitas durante la solicitud actual.

python
from flask import Flask, g

app = Flask(__name__)

# Inicializa el contador antes de cada solicitud
@app.before_request
def iniciar_contador():
  if 'visitas' not in g:
      g.visitas = 0  # Inicia el contador en 0

@app.route('/')
def home():
  # Incrementa el contador en cada visita
  g.visitas += 1
  return f"¡Has visitado esta página {g.visitas} veces durante esta solicitud!"

@app.route('/reset')
def reset_contador():
  g.visitas = 0
  return "El contador de visitas se ha reiniciado para esta solicitud."

if __name__ == '__main__':
  app.run(debug=True, port=5000)
  Explicación del código

Inicialización del contador:

  • Usamos @app.before_request para inicializar g.visitas antes de manejar cada solicitud.

Incremento del contador:

  • En la función de la ruta /, simplemente incrementamos el valor de g.visitas y lo mostramos en el navegador.

Reinicio del contador:

  • Creamos una ruta adicional (/reset) que permite restablecer el contador a cero durante la solicitud actual.

Temporalidad:

  • g.visitas solo almacena los datos durante la solicitud actual y se reinicia automáticamente al inicio de una nueva solicitud.

3. Ejemplo práctico: Conexión a la base de datos

Un caso común de uso de g es para almacenar y compartir la conexión a la base de datos:

python
from flask import Flask, g
import sqlite3

app = Flask(__name__)

DATABASE = 'example.db'

def get_db():
  if 'db' not in g:
      g.db = sqlite3.connect(DATABASE)
  return g.db

@app.teardown_appcontext
def close_db(exception):
  db = g.pop('db', None)
  if db is not None:
      db.close()

@app.route('/')
def home():
  db = get_db()
  cursor = db.cursor()
  cursor.execute("SELECT 'Hola desde la base de datos!'")
  message = cursor.fetchone()[0]
  return message

if __name__ == '__main__':
  app.run(debug=True, port=5000)
  Importante

Conexión a la base de datos:

  • get_db() establece la conexión solo si no existe ya en g. Cierre de la conexión:
  • @app.teardown_appcontext asegura que la conexión se cierre al final de la solicitud.