Flask: MVC
Aprende a implementar el patrón MVC (Modelo-Vista-Controlador) en Flask, organiza controladores y aprovecha la potencia de Jinja para generar vistas dinámicas. Mejora la mantenibilidad y la claridad de tu proyecto web en Python.
Aprende Flask GRATIS y certifícateEn el desarrollo de aplicaciones web con Flask, la adopción de un patrón MVC (Modelo-Vista-Controlador) brinda una estructura limpia y ordenada, facilitando la separación de responsabilidades. Con el microframework Flask, y la integración de Jinja como motor de plantillas, se obtienen vistas dinámicas y flexibles para la capa de presentación.
Qué es el patrón MVC
El patrón MVC consiste en dividir la aplicación en tres componentes principales:
- Modelo (Model): Gestiona la lógica de la aplicación relacionada con los datos, usualmente enlazado con la base de datos.
- Vista (View): Se encarga de la representación visual de la información, habitualmente mediante plantillas.
- Controlador (Controller): Actúa como intermediario, recibiendo las peticiones del usuario y orquestando la interacción entre el modelo y la vista.
En Flask, los modelos suelen desarrollarse con librerías como SQLAlchemy, las vistas se construyen con Jinja y los controladores se establecen a través de funciones que manejan las rutas.
Organización en Flask
Una estructura recomendable para proyectos de tamaño medio o grande en Flask podría ser la siguiente:
mi_proyecto/
├── app.py
├── config.py
├── models/
│ └── usuario.py
├── controllers/
│ └── usuario_controller.py
├── templates/
│ └── usuario/
│ └── detalle.html
│ └── lista.html
├── static/
│ └── css/
│ └── js/
└── requirements.txt
- app.py: Contiene la aplicación Flask y la configuración inicial.
- models/: Aloja las entidades que representan las tablas de la base de datos.
- controllers/: Contiene los archivos que gestionan la lógica de cada recurso o entidad.
- templates/: Carpeta para las vistas de Jinja, separadas por secciones.
- static/: Para archivos estáticos como CSS, JavaScript o imágenes.
Definición de modelos
En la carpeta models, se puede ubicar una clase que represente, por ejemplo, un usuario en la base de datos:
# models/usuario.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Usuario(db.Model):
__tablename__ = 'usuarios'
id = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(50), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return f'<Usuario {self.nombre}>'
Este archivo define el modelo que interactúa con la base de datos, aportando la columna id
como clave primaria, así como nombre
y email
para los datos del usuario.
Controladores y rutas
En Flask, cada ruta se asocia a una función (u objeto) que orquesta la lógica principal. En el patrón MVC, esas funciones representan el controlador. Un ejemplo de controlador para usuarios:
# controllers/usuario_controller.py
from flask import Blueprint, render_template, request, redirect, url_for
from models.usuario import Usuario, db
usuario_bp = Blueprint('usuario_bp', __name__)
@usuario_bp.route('/usuarios', methods=['GET'])
def lista_usuarios():
usuarios = Usuario.query.all()
return render_template('usuario/lista.html', usuarios=usuarios)
@usuario_bp.route('/usuarios/<int:usuario_id>', methods=['GET'])
def detalle_usuario(usuario_id):
usuario = Usuario.query.get_or_404(usuario_id)
return render_template('usuario/detalle.html', usuario=usuario)
@usuario_bp.route('/usuarios/crear', methods=['POST'])
def crear_usuario():
nombre = request.form.get('nombre')
email = request.form.get('email')
nuevo_usuario = Usuario(nombre=nombre, email=email)
db.session.add(nuevo_usuario)
db.session.commit()
return redirect(url_for('usuario_bp.lista_usuarios'))
Aquí se ilustran tres rutas:
- lista_usuarios: Devuelve la lista completa de usuarios consultando el modelo.
- detalle_usuario: Muestra la información de un usuario en particular.
- crear_usuario: Procesa un formulario enviado por método POST, crea un registro en la base de datos y redirige a la lista.
Para usar este controlador, se registra en app.py
(o en un archivo principal), de la siguiente manera:
from flask import Flask
from controllers.usuario_controller import usuario_bp
from models.usuario import db
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mi_base.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
app.register_blueprint(usuario_bp)
with app.app_context():
db.create_all()
if __name__ == '__main__':
app.run(debug=True)
Uso de plantillas Jinja
La capa de vista en el patrón MVC de Flask se maneja mediante Jinja. Este motor de plantillas lee archivos HTML y permite incluir variables y estructuras de control. Un ejemplo en templates/usuario/lista.html
:
<!DOCTYPE html>
<html>
<head>
<title>Lista de usuarios</title>
</head>
<body>
<h1>Lista de usuarios</h1>
<ul>
{% for usuario in usuarios %}
<li>
<a href="{{ url_for('usuario_bp.detalle_usuario', usuario_id=usuario.id) }}">
{{ usuario.nombre }} ({{ usuario.email }})
</a>
</li>
{% endfor %}
</ul>
</body>
</html>
La variable usuarios, pasada desde el controlador, se itera con la sintaxis {% for ... in ... %}
y se muestra el nombre y el correo.
Otra plantilla para templates/usuario/detalle.html
podría:
<!DOCTYPE html>
<html>
<head>
<title>Detalle del usuario</title>
</head>
<body>
<h1>Detalle de {{ usuario.nombre }}</h1>
<p>Correo: {{ usuario.email }}</p>
<a href="{{ url_for('usuario_bp.lista_usuarios') }}">Volver a la lista</a>
</body>
</html>
Mediante Jinja, se mezcla lógica mínima de presentación con variables y enlaces que devuelven información dinámica al usuario.
Formularios y envío de datos
Para crear un nuevo usuario, se puede ofrecer un formulario en una plantilla:
<form action="{{ url_for('usuario_bp.crear_usuario') }}" method="POST">
<label for="nombre">Nombre</label>
<input type="text" name="nombre" id="nombre" required>
<label for="email">Email</label>
<input type="email" name="email" id="email" required>
<button type="submit">Crear</button>
</form>
Al enviarse, la ruta usuario_bp.crear_usuario
gestiona los datos y los inserta en la base de datos. Esta arquitectura en Flask separa claramente la vista (HTML) del controlador (lógica de inserción).
Buenas prácticas en el patrón MVC
- Separar la lógica de negocio (modelos) de la lógica de control (rutas).
- Ubicar archivos HTML en
templates/
, agrupados por sección para mantener orden. - Emplear Blueprints para dividir el proyecto en múltiples controladores, cada uno enfocado en un recurso o módulo distinto.
- Reutilizar partes de la vista con la herencia de plantillas de Jinja, a través de archivos base y bloques que se extienden en subplantillas.
- Definir funciones claras y pequeñas en los controladores, facilitando la lectura y la testabilidad del código.
Extensión con un sistema de archivos estáticos
El directorio static/ se utiliza para hospedar archivos CSS, JavaScript o imágenes. En Flask, se accede a estos recursos a través de la ruta /static
. Por ejemplo, si se ubica un archivo styles.css
dentro de static/css/
, se puede enlazar en una plantilla:
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
Esta organización ofrece coherencia entre los módulos, los assets y las plantillas del proyecto.
Al llevar el patrón MVC a tu aplicación de Flask, se favorece la escalabilidad, la legibilidad y la coherencia de todo el proyecto. Separar el código en modelos, controladores y vistas no solo mejora el mantenimiento, sino que también agiliza el crecimiento y la incorporación de nuevas funcionalidades en la aplicación. Con la potencia de Jinja como motor de plantillas, la creación de interfaces dinámicas se adapta con naturalidad a las necesidades de cada proyecto web en Python.
Lecciones de este módulo de Flask
Lecciones de programación del módulo MVC del curso de Flask.
Controlador Mvc Con Métodos Get En Flask
Sintaxis De Plantillas Jinja 2 En Flask
Controlador Mvc Con Métodos Post En Flask
Validación De Formularios Con Wtforms
Subir Archivos En Formularios Jinja En Flask
Inclusión De Archivos Estáticos En Jinja
Controlador Mvc Con Métodos Post En Flask
Autenticación Con Flask-login
Autenticación Con Flask-login
Autorización Con Flask-principal
Ejercicios de programación en este módulo de Flask
Evalúa tus conocimientos en MVC con ejercicios de programación MVC de tipo Test, Puzzle, Código y Proyecto con VSCode.