Flask Extensions & Middleware

🧩 Common extensions

ExtensionPurpose
Flask-SQLAlchemyORM
Flask-MigrateDB migrations
Flask-WTFforms + CSRF
Flask-Loginsessions/auth
Flask-Mailsend email
Flask-CORScross-origin requests
Flask-Cachingcaching
Flask-Limiterrate limiting
Flask-Sessionserver-side sessions
Flask-Marshmallowserialization/validation

Pattern: ext = Extension() then ext.init_app(app) β€” nearly universal across extensions.

Flask-Mail

pip install flask-mail
from flask_mail import Mail, Message
app.config["MAIL_SERVER"] = "smtp.gmail.com"
app.config["MAIL_PORT"] = 587
app.config["MAIL_USE_TLS"] = True
mail = Mail(app)
 
msg = Message("Welcome!", sender="noreply@myapp.com", recipients=[user_email])
msg.body = "Thanks for signing up."
mail.send(msg)

Flask-Limiter

pip install flask-limiter
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
 
limiter = Limiter(app=app, key_func=get_remote_address, default_limits=["200 per day"])
 
@app.route("/api/login", methods=["POST"])
@limiter.limit("5 per minute")   # tighter limit on sensitive routes
def login(): ...

πŸͺ before_request

@app.before_request
def log_request():
    app.logger.info(f"{request.method} {request.path}")
 
@app.before_request
def check_maintenance():
    if maintenance_mode() and request.path != "/maintenance":
        return render_template("maintenance.html"), 503   # returning a value short-circuits the actual route

πŸͺ after_request

@app.after_request
def add_security_headers(response):
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["X-Frame-Options"] = "DENY"
    return response   # must return it

πŸͺ teardown_request

@app.teardown_request
def close_db(exception=None):
    db = getattr(g, "db_connection", None)
    if db is not None:
        db.close()

teardown_request runs no matter what (even on unhandled exceptions). after_request only runs on success.

🌐 g object β€” per-request storage

from flask import g
 
@app.before_request
def load_user():
    g.user = User.query.get(session.get("user_id"))
 
@app.route("/profile")
def profile():
    return g.user.username if g.user else "Not logged in"

g resets on every new request β€” not for cross-request storage.

🧱 WSGI middleware (rare, low-level)

class SimpleMiddleware:
    def __init__(self, app):
        self.app = app
    def __call__(self, environ, start_response):
        print(environ.get("PATH_INFO"))
        return self.app(environ, start_response)
 
app.wsgi_app = SimpleMiddleware(app.wsgi_app)

πŸ”— Next

Flask File Uploads & Caching Β· Flask Testing & Deployment