Flask: MVC
Descubre cómo implementar el patrón MVC en Flask para crear aplicaciones web escalables y mantenibles con modelos, vistas y controladores.
Aprende Flask GRATIS y certifícateArquitectura MVC en Flask
El patrón Model-View-Controller (MVC) representa uno de los paradigmas arquitectónicos más utilizados en el desarrollo web moderno. En Flask, aunque el framework no impone una estructura MVC estricta por defecto, implementar este patrón resulta fundamental para crear aplicaciones escalables y mantenibles.
Fundamentos del patrón MVC
La arquitectura MVC divide una aplicación en tres componentes interconectados, cada uno con responsabilidades específicas y bien definidas. Esta separación permite que los desarrolladores trabajen en diferentes aspectos de la aplicación sin interferir entre sí.
El Modelo gestiona los datos y la lógica de negocio de la aplicación. En Flask, esto incluye la definición de estructuras de datos, validaciones, operaciones de base de datos y reglas de negocio. Los modelos actúan como la fuente única de verdad para los datos de la aplicación.
La Vista se encarga de la presentación de los datos al usuario. En el contexto de Flask, las vistas son típicamente plantillas HTML que reciben datos del controlador y los presentan de forma estructurada y atractiva.
El Controlador actúa como intermediario entre el modelo y la vista. Procesa las peticiones del usuario, interactúa con los modelos para obtener o modificar datos, y selecciona la vista apropiada para mostrar la respuesta.
Implementación de modelos en Flask
Los modelos en Flask se implementan comúnmente utilizando SQLAlchemy, que proporciona un ORM robusto para la gestión de datos. Un modelo típico define la estructura de una tabla de base de datos y encapsula la lógica relacionada con esa entidad.
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class Usuario(db.Model):
__tablename__ = 'usuarios'
id = db.Column(db.Integer, primary_key=True)
nombre = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
fecha_registro = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return f'<Usuario {self.nombre}>'
def to_dict(self):
return {
'id': self.id,
'nombre': self.nombre,
'email': self.email,
'fecha_registro': self.fecha_registro.isoformat()
}
Los modelos también pueden incluir métodos de clase para operaciones comunes como búsquedas o validaciones específicas:
class Usuario(db.Model):
# ... campos anteriores ...
@classmethod
def buscar_por_email(cls, email):
return cls.query.filter_by(email=email).first()
def validar_email(self):
import re
patron = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(patron, self.email) is not None
Controladores y rutas en Flask
Los controladores en Flask se implementan mediante funciones de vista que manejan las rutas HTTP. Estas funciones procesan las peticiones, interactúan con los modelos y devuelven respuestas apropiadas.
from flask import Blueprint, render_template, request, redirect, url_for, flash
usuarios_bp = Blueprint('usuarios', __name__, url_prefix='/usuarios')
@usuarios_bp.route('/')
def listar_usuarios():
usuarios = Usuario.query.all()
return render_template('usuarios/lista.html', usuarios=usuarios)
@usuarios_bp.route('/crear', methods=['GET', 'POST'])
def crear_usuario():
if request.method == 'POST':
nombre = request.form.get('nombre')
email = request.form.get('email')
# Validación básica
if not nombre or not email:
flash('Todos los campos son obligatorios', 'error')
return render_template('usuarios/crear.html')
# Crear nuevo usuario
usuario = Usuario(nombre=nombre, email=email)
if not usuario.validar_email():
flash('Email no válido', 'error')
return render_template('usuarios/crear.html')
db.session.add(usuario)
db.session.commit()
flash('Usuario creado exitosamente', 'success')
return redirect(url_for('usuarios.listar_usuarios'))
return render_template('usuarios/crear.html')
La organización en Blueprints permite estructurar los controladores de forma modular, agrupando rutas relacionadas y facilitando el mantenimiento del código.
Vistas y plantillas
Las vistas en Flask utilizan el motor de plantillas Jinja2 para generar contenido HTML dinámico. Las plantillas reciben datos del controlador y los presentan de forma estructurada.
<!-- templates/usuarios/lista.html -->
{% extends "base.html" %}
{% block title %}Lista de Usuarios{% endblock %}
{% block content %}
<div class="container">
<h1>Usuarios Registrados</h1>
<a href="{{ url_for('usuarios.crear_usuario') }}" class="btn btn-primary">
Nuevo Usuario
</a>
<div class="usuarios-grid">
{% for usuario in usuarios %}
<div class="usuario-card">
<h3>{{ usuario.nombre }}</h3>
<p>{{ usuario.email }}</p>
<small>Registrado: {{ usuario.fecha_registro.strftime('%d/%m/%Y') }}</small>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
Las plantillas pueden incluir lógica condicional y bucles para presentar datos de forma dinámica:
<!-- templates/usuarios/crear.html -->
{% extends "base.html" %}
{% block content %}
<div class="form-container">
<h2>Crear Nuevo Usuario</h2>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="POST">
<div class="form-group">
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<button type="submit">Crear Usuario</button>
</form>
</div>
{% endblock %}
Estructura de directorios MVC
Una aplicación Flask bien estructurada siguiendo el patrón MVC organiza los archivos de forma lógica y escalable:
mi_aplicacion/
├── app/
│ ├── __init__.py
│ ├── models/
│ │ ├── __init__.py
│ │ ├── usuario.py
│ │ └── producto.py
│ ├── controllers/
│ │ ├── __init__.py
│ │ ├── usuarios.py
│ │ └── productos.py
│ ├── templates/
│ │ ├── base.html
│ │ ├── usuarios/
│ │ │ ├── lista.html
│ │ │ └── crear.html
│ │ └── productos/
│ │ ├── lista.html
│ │ └── detalle.html
│ └── static/
│ ├── css/
│ ├── js/
│ └── img/
├── config.py
└── run.py
Integración de componentes MVC
La integración efectiva de los componentes MVC requiere una comunicación clara entre las capas. Los controladores actúan como orquestadores, coordinando las operaciones entre modelos y vistas:
@usuarios_bp.route('/<int:usuario_id>')
def detalle_usuario(usuario_id):
# El controlador solicita datos al modelo
usuario = Usuario.query.get_or_404(usuario_id)
# Puede realizar operaciones adicionales
estadisticas = {
'total_pedidos': usuario.pedidos.count(),
'ultimo_acceso': usuario.ultimo_acceso
}
# Pasa los datos a la vista
return render_template('usuarios/detalle.html',
usuario=usuario,
estadisticas=estadisticas)
Esta separación de responsabilidades facilita el testing, el mantenimiento y la escalabilidad de la aplicación, permitiendo modificar cada componente de forma independiente sin afectar a los demás.
Lecciones de este módulo de Flask
Lecciones de programación del módulo MVC del curso de Flask.
Inclusión De Archivos Estáticos En Jinja
Controlador Mvc Con Métodos Get En Flask
Validación De Formularios Con Wtforms
Subir Archivos En Formularios Jinja En Flask
Autenticación Con Flask-login
Sintaxis Jinja2
Controlador Mvc Con Métodos Post En Flask
Sintaxis De Plantillas Jinja 2 En Flask
Controlador Mvc Con Métodos Post En Flask
Autorización Con Flask-principal
Flash Messages
Introducción Al Patrón Mvc
Autenticación Con Flask-login
Blueprints
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.