7.6 Visualización y modificación de datos desde la base
Reemplazarás la simulación por datos reales. Aprenderás a consultar la base de datos, mostrar los resultados y permitir editar o eliminar tareas existentes.
Reemplazarás la simulación por datos reales. Aprenderás a consultar la base de datos, mostrar los resultados y permitir editar o eliminar tareas existentes.
En app.py, importa Flask, los modelos Tarea , Categoria e inicialización de base de datos desde database.py:
from flask import Flask, render_template, request, redirectfrom database import init_dbfrom models.categoria import Categoriafrom models.tarea import Tarea
Esto permite que tus rutas accedan a la base de datos y trabajen con objetosTareacon suCategoriaasociada en toda la app.
A cada ruta se le asignará una función definida en database.py y una vista HTML correspondiente. Cada ruta representa una acción específica sobre el modelo tares:
/tareas para listar todas las tareas./crear para crear una nueva./tarea/<id> para ver una tarea específica./editar/edit para editarla./eliminar/<id> para borrarla.Este esquema permite visualizar la arquitectura de tu aplicación antes de implementar cada función y vistas.
Crea tus archivos html, nombrándolos con una convención clara y común en desarrollo web:
├── index.html # Listar tareas├── formulario.html # Formulario para crear├── tarea.html # Detalle de una tarea└── editar.html # Formulario de edición
Desde tus rutas, puedes llamar estas vistas con:
return render_template("index.html", tareas=tareas)
Esta estructura mantiene el proyecto limpio y escalable conforme se agregan más modelos o funcionalidades.
@app.route('/crear', methods=['GET', 'POST'])def nueva_tarea():if request.method == 'POST':nombre = request.form['title']categoria_id = request.form['category_id']Tarea.create(nombre=nombre,categoria_id=categoria_id)return redirect('/')categorias = Categoria.get_all()return render_template("formulario.html", categorias=categorias)
Vista HTML – ./formulario.html
<h1>Nueva tarea</h1><form method="POST"><label for="title">Título:</label><input type="text" id="title" name="title" required><label for="category_id">Categoría:</label><select id="category_id" name="category_id" required>{% for categoria in categorias %}<option value="{{ categoria.id }}">{{ categoria.name }}</option>{% endfor %}</select><button type="submit">Guardar</button></form>
<h1>Lista de tareas</h1><ul>{% for tarea in tareas %}<li>{{ tarea.title }} - {{ tarea.status }}<a href="/tarea/{{ tarea.id }}">Ver</a><a href="/editar/{{ tarea.id }}">Editar</a><form action="/eliminar/{{ tarea.id }}" method="POST"><button type="submit">Eliminar</button></form></li>{% endfor %}</ul><a href="/crear">Agregar nueva tarea</a>
@app.route('/tarea/<int:id>')def ver_tarea(id):tarea = Tarea.get_by_id(id)return render_template("tarea.html", tarea=tarea)
Vista HTML – templates/tarea.html:
<h1>Detalle de tarea</h1><p><strong>Título:</strong> {{ tarea.nombre }}</p><p><strong>Estado:</strong> {{ tarea.estado }}</p><a href="/editar/{{ tarea.id }}">Editar</a> |<form action="/eliminar/{{ tarea.id }}" method="POST"><button type="submit">Eliminar</button></form>
En la vista de edición es buena práctica seleccionar automáticamente con los datos actuales.
<!-- Vista HTML – templates/editar.html: --><form method="POST"><input type="text" id="title" name="title" value="{{ tarea.nombre }}" required><select id="status" name="status"><option value="pendiente" {% if tarea.estado=='pendiente' %}selected{% endif %}>Pendiente</option><option value="completada" {% if tarea.estado=='completada' %}selected{% endif %}>Completada</option></select><select id="category_id" name="category_id" required>{% for categoria in categorias %}<option value="{{ categoria.id }}"{% if categoria.id == tarea.categoria_id %}selected{% endif %}>{{ categoria.name }}</option>{% endfor %}</select><button type="submit">Guardar cambios</button></form>
Cada <select> usa {% if ... selected %} para marcar el valor actual, lo cual es esencial al trabajar con formularios que editan datos existentes.
@app.route('/editar/<int:id>', methods=['GET', 'POST'])def editar_tarea(id):tarea = Tarea.get_by_id(id)if request.method == 'POST':id = request.form['id']nombre = request.form['title']estado = request.form['status']Tarea.update(id, nombre)# Aquí puedes invocar a más actualización de métodos,# según los atributos de tus modelos,# como asignación de fechas actuales u operacionesif tarea.estado != estadoTarea.set_estado(estado)return redirect('/tareas')categorias = Categoria.get_all()return render_template("editar.html", tarea=tarea, categorias=categorias)
@app.route('/eliminar/<int:id>', methods=['POST'])def eliminar_tarea(id):Tarea.delete(id)return redirect('/tareas')
Vistas HTML – tarea.html o index.html:
<form action="/eliminar/{{ tarea.id }}" method="POST" style="display:inline;"><button type="submit">Eliminar</button></form>
Se usa POST en lugar de GET para evitar eliminaciones accidentales al hacer clic en un enlace o al recargar la página. No se muestra un enlace directo como <a href="/eliminar/...">, ya que esto violaría buenas prácticas de seguridad.
Podrías mejorar esta acción mediante Javascript, con una confirmación o un token CSRF para asegurar protección.
Tu aplicación ya permite crear, consultar, editar y eliminar tareas usando rutas personalizadas, un modelo Tarea bien definido y funciones reutilizables desde database.py.
Has aplicado buenas prácticas como la separación de responsabilidades, uso de plantillas organizadas y manejo de datos estructurados con SQLite.
Si quieres seguir profundizando en Flask y mejorar tu proyecto, te recomiendo estos recursos: