Tutorial Flask: Construye una Aplicación Web CRUD con SQLite y Python
Bienvenido a este tutorial detallado para desarrolladores principiantes e intermedios interesados en crear una aplicación CRUD (Crear, Leer, Actualizar, Eliminar) utilizando Flask y SQLite en Python. Aquí aprenderás paso a paso cómo configurar tu entorno, definir rutas, integrar la base de datos con SQLAlchemy, manejar formularios con validación y desplegar tu proyecto básico. Este tutorial es ideal para quienes desean profundizar en el desarrollo backend y la programación web con Python.
Tabla de contenidos
- Configuración del entorno
- Creación del proyecto Flask
- Configuración y conexión a SQLite con SQLAlchemy
- Definición de rutas y vistas CRUD
- Manejo de formularios y validación
- Despliegue básico de la aplicación
- Conclusión y buenas prácticas
Configuración del entorno
Antes de comenzar, asegúrate de tener instalado Python 3.6 o superior. Vamos a crear un entorno virtual para mantener las dependencias aisladas.
Paso 1: Crear y activar un entorno virtual
1 2 3 4 5 6 7 8 9 |
# Crear entorno virtual python -m venv venv # Activar entorno virtual (Windows) venv\Scripts\activate # Activar entorno virtual (macOS/Linux) source venv/bin/activate |
Paso 2: Instalar Flask y dependencias
1 2 |
pip install Flask Flask-SQLAlchemy Flask-WTF |
- Flask: microframework para desarrollo web.
- Flask-SQLAlchemy: ORM que facilita la integración con bases de datos.
- Flask-WTF: gestión y validación de formularios.
Creación del proyecto Flask
Crea un proyecto nuevo con una estructura básica:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
flask_crud_app/ │ ├── app.py ├── config.py ├── templates/ │ ├── base.html │ ├── index.html │ ├── create.html │ ├── edit.html │ └── static/ └── style.css |
Explicación:
app.py
: archivo principal donde definiremos nuestra app Flask.config.py
: configuraciones generales.templates/
: contiene los archivos HTML de las vistas.static/
: para archivos estáticos como CSS.
Configuración y conexión a SQLite con SQLAlchemy
Paso 1: Crear el archivo config.py
1 2 3 4 5 6 7 8 9 |
import os BASE_DIR = os.path.abspath(os.path.dirname(__file__)) class Config: SECRET_KEY = 'tu_clave_secreta_aqui' # Imprescindible para proteger formularios SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, 'app.db') SQLALCHEMY_TRACK_MODIFICATIONS = False |
- El
SECRET_KEY
es necesario para gestionar la seguridad de formularios. - La base de datos SQLite estará en el archivo
app.db
.
Paso 2: Inicializar Flask y SQLAlchemy en app.py
1 2 3 4 5 6 7 8 9 10 11 |
from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_wtf import FlaskForm from config import Config app = Flask(__name__) app.config.from_object(Config) db = SQLAlchemy(app) |
Definición de rutas y vistas CRUD
Paso 1: Crear el modelo de datos
En el archivo app.py
, definiremos un modelo simple, por ejemplo, una lista de tareas (Task
).
1 2 3 4 5 6 7 8 |
class Task(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100), nullable=False) description = db.Column(db.Text, nullable=True) def __repr__(self): return f'<Task {self.title}>' |
Paso 2: Crear la base de datos
Abre una terminal con el entorno virtual activado y ejecuta:
1 2 3 4 |
from app import db db.create_all() |
Esta acción crea el archivo app.db
con la tabla Task
.
Paso 3: Definir rutas y vistas para cada operación CRUD
Vamos a crear las rutas básicas:
- Listado de tareas – Leer:
/
- Crear tarea:
/create
- Actualizar tarea:
/edit/<id>
- Eliminar tarea:
/delete/<id>
Código completo de rutas en app.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
from flask import render_template, request, redirect, url_for, flash from flask_wtf import FlaskForm from wtforms import StringField, TextAreaField, SubmitField from wtforms.validators import DataRequired # Modelo definido anteriormente aquí # Formularios se añaden aquí (ver siguiente sección) @app.route('/') def index(): tasks = Task.query.all() return render_template('index.html', tasks=tasks) @app.route('/create', methods=['GET', 'POST']) def create(): form = TaskForm() if form.validate_on_submit(): new_task = Task( title=form.title.data, description=form.description.data ) db.session.add(new_task) db.session.commit() flash('Tarea creada correctamente', 'success') return redirect(url_for('index')) return render_template('create.html', form=form) @app.route('/edit/<int:task_id>', methods=['GET', 'POST']) def edit(task_id): task = Task.query.get_or_404(task_id) form = TaskForm(obj=task) # Cargar formulario con datos existentes if form.validate_on_submit(): task.title = form.title.data task.description = form.description.data db.session.commit() flash('Tarea actualizada correctamente', 'success') return redirect(url_for('index')) return render_template('edit.html', form=form) @app.route('/delete/<int:task_id>', methods=['POST']) def delete(task_id): task = Task.query.get_or_404(task_id) db.session.delete(task) db.session.commit() flash('Tarea eliminada correctamente', 'success') return redirect(url_for('index')) if __name__ == '__main__': app.run(debug=True) |
Manejo de formularios y validación
Utilizaremos Flask-WTF para crear y validar formularios de manera sencilla.
Paso 1: Definir formulario en app.py
1 2 3 4 5 |
class TaskForm(FlaskForm): title = StringField('Título', validators=[DataRequired(message='El título es obligatorio')]) description = TextAreaField('Descripción') submit = SubmitField('Guardar') |
DataRequired
: obliga a que el campotitle
no quede vacío.
Paso 2: Crear las plantillas HTML dentro de templates/
A continuación te mostramos los archivos HTML con comentarios.
templates/base.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>{% block title %}Flask CRUD App{% endblock %}</title> <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> </head> <body> <header> <h1>Aplicación CRUD con Flask y SQLite</h1> <nav> <a href="{{ url_for('index') }}">Inicio</a> <a href="{{ url_for('create') }}">Crear Tarea</a> </nav> </header> <main> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} <ul class="flashes"> {% for category, message in messages %} <li class="{{ category }}">{{ message }}</li> {% endfor %} </ul> {% endif %} {% endwith %} {% block content %} {% endblock %} </main> </body> </html> |
templates/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
{% extends "base.html" %} {% block title %}Lista de Tareas{% endblock %} {% block content %} <h2>Lista de Tareas</h2> {% if tasks %} <table> <thead> <tr> <th>ID</th> <th>Título</th> <th>Descripción</th> <th>Acciones</th> </tr> </thead> <tbody> {% for task in tasks %} <tr> <td>{{ task.id }}</td> <td>{{ task.title }}</td> <td>{{ task.description or 'Sin descripción' }}</td> <td> <a href="{{ url_for('edit', task_id=task.id) }}">Editar</a> | <form action="{{ url_for('delete', task_id=task.id) }}" method="POST" style="display:inline;"> <button type="submit" onclick="return confirm('¿Seguro que deseas eliminar esta tarea?');">Eliminar</button> </form> </td> </tr> {% endfor %} </tbody> </table> {% else %} <p>No hay tareas registradas.</p> {% endif %} {% endblock %} |
templates/create.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{% extends "base.html" %} {% block title %}Crear Nueva Tarea{% endblock %} {% block content %} <h2>Crear Nueva Tarea</h2> <form method="POST"> {{ form.hidden_tag() }} <!-- Protección CSRF --> <p> {{ form.title.label }}<br> {{ form.title(size=50) }}<br> {% for error in form.title.errors %} <span class="error">{{ error }}</span> {% endfor %} </p> <p> {{ form.description.label }}<br> {{ form.description(rows=5, cols=50) }} </p> <p>{{ form.submit() }}</p> </form> {% endblock %} |
templates/edit.html
Muy similar a create.html
, permitiendo actualizar una tarea:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{% extends "base.html" %} {% block title %}Editar Tarea{% endblock %} {% block content %} <h2>Editar Tarea</h2> <form method="POST"> {{ form.hidden_tag() }} <p> {{ form.title.label }}<br> {{ form.title(size=50) }}<br> {% for error in form.title.errors %} <span class="error">{{ error }}</span> {% endfor %} </p> <p> {{ form.description.label }}<br> {{ form.description(rows=5, cols=50) }} </p> <p>{{ form.submit() }}</p> </form> {% endblock %} |
Despliegue básico de la aplicación
Para ejecutar nuestra aplicación de forma local, basta ejecutar:
1 2 |
python app.py |
Esto ejecutará el servidor Flask en http://127.0.0.1:5000/
. Navega a esa URL en tu navegador.
Para un despliegue básico en un entorno de producción (no detallado aquí), puedes considerar:
- Usar un servidor web WSGI como Gunicorn o uWSGI.
- Servir la aplicación detrás de un proxy reverso como Nginx.
- Configurar variables de entorno para el
SECRET_KEY
y configuraciones sensibles.
Comando Gunicorn ejemplo (Linux/macOS)
1 2 |
gunicorn -w 4 -b 0.0.0.0:8000 app:app |
Donde:
-w 4
: usa 4 trabajadores.-b
: bind, dirección IP y puerto.
Conclusión y buenas prácticas
En este tutorial has aprendido a:
- Configurar un entorno virtual y dependencias con Flask, SQLAlchemy y Flask-WTF.
- Crear una aplicación web básica con Flask.
- Definir un modelo de datos para SQLite con SQLAlchemy.
- Crear rutas y vistas para operaciones CRUD.
- Manejar formularios y validar entradas con Flask-WTF.
- Desplegar la app localmente y conocer opciones básicas para producción.
Buenas prácticas recomendadas
- Mantén tu
SECRET_KEY
seguro y no lo subas a repositorios públicos. - Organiza el proyecto por módulos si crece (usar Blueprints).
- Implementa manejo de errores y validaciones más robustas.
- Usa migraciones con Flask-Migrate para administrar cambios en BD.
- Asegúrate de validar y sanear todas las entradas de usuarios.
- Implementa pruebas unitarias para asegurar estabilidad.
¡Ahora estás listo para crear aplicaciones web robustas y escalables con Python! Si quieres profundizar más, explora autenticación de usuarios, APIs REST y frameworks frontend para complementar tu aplicación.
¿Te ha gustado este tutorial Flask?
No olvides guardar este artículo, compartirlo con otros desarrolladores y seguir aprendiendo programación web Python con proyectos prácticos. ¡Manos a la obra!