Introducción a Flask

Framework web ligero para Python, rutas, plantillas Jinja2, bases de datos y despliegue

Objetivos de Aprendizaje

¿Qué es Flask?

Microframework para Python

Flask es un microframework web para Python, lo que significa que proporciona las herramientas esenciales para construir aplicaciones web sin imponer una estructura rígida o dependencias excesivas. Es ideal para proyectos pequeños y medianos, APIs RESTful y prototipos rápidos.

Ligero y Flexible

Mínima curva de aprendizaje, gran libertad de diseño

Basado en Werkzeug y Jinja2

Utiliza componentes probados para WSGI y plantillas

Extensible

Gran ecosistema de extensiones para añadir funcionalidades

Fácil de Usar

Sintaxis intuitiva y documentación clara

Hola Mundo en Flask

# app.py
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify

app = Flask(__name__)
app.config["SECRET_KEY"] = "una_clave_secreta_muy_segura"

@app.route("/")
def index():
    return "

¡Hola, mundo desde Flask!

" @app.route("/saludar/") def saludar(nombre): return f"

¡Hola, {nombre}! Bienvenido a Flask.

" @app.route("/suma//") def suma(a, b): resultado = a + b return f"

La suma de {a} y {b} es: {resultado}

" @app.route("/contacto", methods=["GET", "POST"]) def contacto(): if request.method == "POST": nombre = request.form["nombre"] email = request.form["email"] mensaje = request.form["mensaje"] flash(f"Mensaje de {nombre} ({email}) recibido: {mensaje}", "success") return redirect(url_for("index")) return render_template("contacto.html") @app.route("/api/data") def api_data(): data = { "nombre": "API de Ejemplo", "version": "1.0", "recursos": [ {"id": 1, "item": "Elemento A"}, {"id": 2, "item": "Elemento B"} ] } return jsonify(data) if __name__ == "__main__": app.run(debug=True)

Rutas y Plantillas Jinja2

Manejo de Rutas

Flask utiliza decoradores para asociar funciones Python con URLs específicas, permitiendo manejar diferentes métodos HTTP y parámetros dinámicos.

Rutas Básicas y Dinámicas

# app.py (rutas)
@app.route("/")
def home():
    return "Página de inicio"

@app.route("/usuario/")
def show_user_profile(username):
    return f"Perfil de usuario: {username}"

@app.route("/post/")
def show_post(post_id):
    return f"Post ID: {post_id}"

@app.route("/path/")
def show_subpath(subpath):
    return f"Subruta: {subpath}"

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form["username"]
        password = request.form["password"]
        if username == "admin" and password == "password":
            flash("Inicio de sesión exitoso", "success")
            return redirect(url_for("dashboard"))
        else:
            flash("Credenciales inválidas", "danger")
    return render_template("login.html")

Plantillas Jinja2

Jinja2 es el motor de plantillas por defecto de Flask, permitiendo crear HTML dinámico con lógica de programación, herencia de plantillas y macros.

Uso de Jinja2

<!-- base.html -->
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Mi Aplicación Flask{% endblock %}</title>
    <link rel="stylesheet" href="{{ url_for("static", filename="style.css") }}">
</head>
<body>
    <header>
        <nav>
            <a href="{{ url_for("index") }}">Inicio</a>
            <a href="{{ url_for("contacto") }}">Contacto</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>
    <footer>
        <p>© {{ "now"|date("%Y") }} Mi Aplicación Flask.</p>
    </footer>
</body>
</html>

<!-- index.html -->
{% extends "base.html" %}

{% block title %}Página Principal{% endblock %}

{% block content %}
    <h1>Bienvenido a mi sitio Flask</h1>
    <p>Explora las funcionalidades de Flask.</p>
    <ul>
        {% for item in items %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
{% endblock %}

Bases de Datos y Despliegue

Integración con Bases de Datos (SQLAlchemy)

Flask no incluye un ORM por defecto, pero Flask-SQLAlchemy es una extensión popular que facilita la interacción con bases de datos relacionales.

Flask-SQLAlchemy

# app.py (con SQLAlchemy)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///site.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)
    posts = db.relationship("Post", backref="author", lazy=True)

    def __repr__(self):
        return f"User(\'{self.username}\', \'{self.email}\')"

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    content = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

    def __repr__(self):
        return f"Post(\'{self.title}\', \'{self.date_posted}\')"

# Para crear la base de datos y tablas (ejecutar una vez)
# with app.app_context():
#     db.create_all()

# Ejemplo de uso en una ruta
@app.route("/add_user")
def add_user():
    with app.app_context():
        new_user = User(username="testuser", email="test@example.com", password="password123")
        db.session.add(new_user)
        db.session.commit()
    return "Usuario añadido!"

@app.route("/users")
def get_users():
    with app.app_context():
        users = User.query.all()
        user_list = [{"username": u.username, "email": u.email} for u in users]
    return jsonify(user_list)

Despliegue de Aplicaciones Flask

Para desplegar aplicaciones Flask en producción, se recomienda usar un servidor WSGI como Gunicorn y un proxy inverso como Nginx.

Flujo de Despliegue

1
Nginx

Proxy inverso, SSL, balanceo de carga

2
Gunicorn

Servidor WSGI, maneja procesos Flask

3
Flask App

Lógica de negocio, rutas, plantillas

Configuración Gunicorn

# wsgi.py
from app import app

if __name__ == "__main__":
    app.run()

# Comando para ejecutar Gunicorn
# gunicorn --workers 4 --bind 0.0.0.0:8000 wsgi:app

# systemd service file (/etc/systemd/system/myflaskapp.service)
[Unit]
Description=Gunicorn instance to serve myflaskapp
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myflaskapp
ExecStart=/usr/bin/gunicorn --workers 4 --bind unix:/var/www/myflaskapp/myflaskapp.sock -m 007 wsgi:app
Restart=always

[Install]
WantedBy=multi-user.target

Configuración Nginx

# /etc/nginx/sites-available/myflaskapp
server {
    listen 80;
    server_name your_domain.com www.your_domain.com;

    location / {
        include proxy_params;
        proxy_pass http://unix:/var/www/myflaskapp/myflaskapp.sock;
    }

    # Para servir archivos estáticos directamente con Nginx
    location /static {
        alias /var/www/myflaskapp/static;
    }
}

# Habilitar el sitio
# sudo ln -s /etc/nginx/sites-available/myflaskapp /etc/nginx/sites-enabled/
# sudo nginx -t
# sudo systemctl restart nginx

Proyecto en GitHub

Aplicación Flask Completa

Aplicación web Flask con autenticación de usuarios, gestión de posts, integración con base de datos y scripts de despliegue, demostrando todos los conceptos de esta semana.

Autenticación

Registro, login y gestión de sesiones de usuario

Gestión de Contenido

Creación, edición y eliminación de posts

Integración DB

Uso de Flask-SQLAlchemy con SQLite/PostgreSQL

Despliegue

Configuraciones para Gunicorn y Nginx

Resumen Semana 15

Fundamentos de Flask

Comprensión de la filosofía de Flask, su ligereza y flexibilidad como microframework.

Rutas y Vistas

Dominio del enrutamiento, manejo de peticiones HTTP y parámetros dinámicos.

Plantillas Jinja2

Creación de HTML dinámico, herencia de plantillas y uso de lógica en el frontend.

Bases de Datos

Integración de bases de datos relacionales con Flask-SQLAlchemy.

Despliegue

Estrategias de despliegue en producción con Gunicorn y Nginx.

Proyecto Completo

Desarrollo de una aplicación Flask funcional con autenticación y gestión de contenido.