Blueprints y vistas
Una función de vista es el código que escribimos para responder a las solicitudes de nuestra aplicación. Flask utiliza patrones para hacer coincidir la URL de solicitud entrante con la vista que debe manejarla. La vista devuelve datos que Flask convierte en una respuesta saliente. Flask también puede hacer lo contrario y generar una URL a una vista basada en su nombre y argumentos.
Crear un Blueprint
Un Blueprint es una forma de organizar un grupo de vistas y otro código relacionado. En lugar de registrar vistas y otro código directamente en una aplicación, se registran con un Blueprint. Luego, el Blueprint se registra en la aplicación cuando está disponible en la función de fábrica.
Flask_todolist tendrá dos Blueprints, uno para funciones de autenticación y otro para funciones de publicaciones de items de la lista. El código para cada Blueprint se colocará en un módulo separado. Dado que el “Todo List” necesita conocer la autenticación, primero escribirás el Blueprint de autenticación.
flask_todolist/auth.py
import functools
from flask import (
Blueprint, flash, g, redirect, render_template, request, session, url_for
)
from werkzeug.security import check_password_hash, generate_password_hash
from flask_todolist.db import get_db
bp = Blueprint('auth', __name__, url_prefix='/auth')
Esto crea un Blueprint llamado 'auth'. Al igual que el objeto de la aplicación, el Blueprint necesita saber dónde se define, por lo que se pasa __name__ como segundo argumento. El url_prefix se añadirá al comienzo de todas las URL asociadas con el Blueprint.
Importa y registra el Blueprint desde la función de fábrica utilizando app.register_blueprint(). Coloca el nuevo código al final de la función de fábrica antes de devolver la aplicación.
flask_todolist/__init__.py
def create_app():
app = ...
# existing code omitted
from . import auth
app.register_blueprint(auth.bp)
return app
El Blueprint de autenticación tendrá vistas para registrar nuevos usuarios, iniciar sesión y cerrar sesión.
La primera vista: Register
Cuando el usuario visita la URL /auth/register, la vista de registro devolverá HTML con un formulario para que lo completen. Cuando envíen el formulario, se validará su entrada y se mostrará nuevamente el formulario con un mensaje de error o se creará un nuevo usuario y se dirigirá a la página de inicio de sesión.
Por ahora solo escribirás el código de la vista. En la siguiente página, escribirás plantillas para generar el formulario HTML.
flask_todolist/auth.py
@bp.route('/register', methods=('GET', 'POST'))
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
db = get_db()
error = None
if not username:
error = 'Username is required.'
elif not password:
error = 'Password is required.'
if error is None:
try:
db.execute(
"INSERT INTO user (username, password) VALUES (?, ?)",
(username, generate_password_hash(password)),
)
db.commit()
except db.IntegrityError:
error = f"User {username} is already registered."
else:
return redirect(url_for("auth.login"))
flash(error)
return render_template('auth/register.html')
Aquí está lo que hace la función de la vista de registro:
Login
Esta vista sigue el mismo patrón que la vista de registro anterior.
flask_todolist/auth.py
@bp.route('/login', methods=('GET', 'POST'))
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
db = get_db()
error = None
user = db.execute(
'SELECT * FROM user WHERE username = ?', (username,)
).fetchone()
if user is None:
error = 'Incorrect username.'
elif not check_password_hash(user['password'], password):
error = 'Incorrect password.'
if error is None:
session.clear()
session['user_id'] = user['id']
return redirect(url_for('index'))
flash(error)
return render_template('auth/login.html')
Hay algunas diferencias con respecto a la vista de registro:
Hay algunas diferencias en la vista de inicio de sesión en comparación con la vista de registro:
Ahora que el id del usuario se almacena en la sesión, estará disponible en solicitudes posteriores. Al comienzo de cada solicitud, si un usuario ha iniciado sesión, su información debe cargarse y ponerse a disposición de otras vistas.
flask_todolist/auth.py
@bp.before_app_request
def load_logged_in_user():
user_id = session.get('user_id')
if user_id is None:
g.user = None
else:
g.user = get_db().execute(
'SELECT * FROM user WHERE id = ?', (user_id,)
).fetchone()
bp.before_app_request() registra una función que se ejecuta antes de la función de vista, sin importar la URL que se solicite. load_logged_in_user verifica si hay un id de usuario almacenado en la sesión y obtiene los datos de ese usuario desde la base de datos, almacenándolos en g.user, que permanece durante toda la duración de la solicitud. Si no hay un id de usuario, o si el id no existe, g.user será None.
Logout
Para cerrar sesión, debes eliminar el id de usuario de la sesión. De esta manera, load_logged_in_user no cargará un usuario en las solicitudes posteriores.
flask_todolist/auth.py
@bp.route('/logout')
def logout():
session.clear()
return redirect(url_for('index'))
Requerir autenticación en otras vistas
Crear, editar y eliminar publicaciones del “Todo List” requerirá que un usuario inicie sesión. Se puede usar un decorador para verificar esto para cada vista a la que se aplica.
flask_todolist/auth.py
def login_required(view):
@functools.wraps(view)
def wrapped_view(**kwargs):
if g.user is None:
return redirect(url_for('auth.login'))
return view(**kwargs)
return wrapped_view
Este decorador devuelve una nueva función de vista que envuelve la vista original a la que se aplica. La nueva función verifica si hay un usuario cargado y, en caso contrario, redirige a la página de inicio de sesión. Si hay un usuario cargado, se llama a la vista original y continúa normalmente. Utilizarás este decorador al escribir las vistas del blog.
Endpoints y URLs
La función url_for() genera la URL hacia una vista basada en su nombre y argumentos. El nombre asociado con una vista también se llama punto final (endpoint) y, por defecto, es el mismo que el nombre de la función de la vista.
Por ejemplo, la vista hello() que se agregó a la fábrica de la aplicación anteriormente en el tutorial tiene el nombre 'hello' y se puede enlazar usando url_for('hello'). Si tomara un argumento, como verás más adelante, se podría enlazar usando url_for('hello', who='Mundo').
Cuando se utiliza un blueprint, el nombre del blueprint se agrega al principio del nombre de la función, por lo que el endpoint para la función de inicio de sesión que escribiste arriba es 'auth.login' porque la agregaste al blueprint 'auth'.
← Definir y acceder a la base de datos | Continúa con Templates →
En este Post aprenderemos a personalizar la tienda Magento 2. Descubre cómo incorporar JavaScript personalizado para mejorar la funcionalidad y ...
Leer más...Current version of RDBMS is not supported. Used Version: 10.6.17-MariaDB-1:10.6.17+maria~ubu2004. Supported versions: MySQL-8, MySQL-5....
Leer más...Los principales motivos para aprenderLa motivación es uno de los pilares fundamentales en el proceso de aprendizaje del desarrollo web....
Leer más...✨ Dominando el Estilo: Un Viaje al Mundo de CSSEn el universo del desarrollo web, CSS (Cascading Style Sheets) desempeña un papel funda...
Leer más...