Flask Cheatsheet
Sessions and Cookies
Use this Flask reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Sessions
Flask's default session is a client-side signed cookie (HMAC-SHA1 using SECRET_KEY). The data is visible to the client but cannot be tampered with. For server-side sessions, use flask-session.
from flask import session # Read user_id = session.get("user_id") # None if key missing theme = session["theme"] # KeyError if missing # Write session["user_id"] = user.id session["cart"] = [1, 2, 3] # Delete one key session.pop("user_id", None) # safe pop (no error if missing) del session["user_id"] # KeyError if missing # Clear all session data session.clear() # Check membership if "user_id" in session: ...
Session Configuration
| Config Key | Default | Description |
|---|---|---|
SECRET_KEY | — | Required. Signs the session cookie. Use a long random value. |
SESSION_COOKIE_NAME | "session" | Cookie name |
SESSION_COOKIE_DOMAIN | None | Domain (None = current host only) |
SESSION_COOKIE_PATH | None | Cookie path (None = APPLICATION_ROOT) |
SESSION_COOKIE_HTTPONLY | True | JS cannot read cookie |
SESSION_COOKIE_SECURE | False | HTTPS-only; set True in production |
SESSION_COOKIE_SAMESITE | None | "Lax", "Strict", or "None" |
PERMANENT_SESSION_LIFETIME | 31 days | timedelta; only applies to permanent sessions |
SESSION_REFRESH_EACH_REQUEST | True | Refresh cookie expiry on each request |
Permanent Sessions
By default, the session cookie expires when the browser closes. Mark it as permanent to set a real expiry:
from datetime import timedelta app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(days=30) @app.route("/login", methods=["POST"]) def login(): session.permanent = True # set before writing to session session["user_id"] = user.id return redirect(url_for("dashboard"))
Generating a Secure SECRET_KEY
python -c "import secrets; print(secrets.token_hex(32))"Store in environment variable, never hard-code in source:
app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY", "dev-only-key")
Custom Session Interface
from flask.sessions import SecureCookieSessionInterface class MySessionInterface(SecureCookieSessionInterface): def should_set_cookie(self, app, session): return session.modified or session.permanent app.session_interface = MySessionInterface()
Server-Side Sessions (flask-session)
pip install flask-session
from flask_session import Session app.config["SESSION_TYPE"] = "filesystem" # or "redis", "sqlalchemy", "memcached" app.config["SESSION_FILE_DIR"] = "/tmp/flask_sessions" app.config["SESSION_PERMANENT"] = False # Note: SESSION_USE_SIGNER was deprecated and removed in flask-session 0.6+ Session(app) # call after config # Now session is server-side; usage is identical to client-side
Redis backend:
import redis app.config["SESSION_TYPE"] = "redis" app.config["SESSION_REDIS"] = redis.from_url("redis://localhost:6379")
SQLAlchemy backend:
app.config["SESSION_TYPE"] = "sqlalchemy" app.config["SESSION_SQLALCHEMY"] = db app.config["SESSION_SQLALCHEMY_TABLE"] = "sessions"
max_age vs expires
| Attribute | Type | Notes |
|---|---|---|
max_age | int (seconds) | Relative; preferred — works in all modern browsers |
expires | datetime or int | Absolute UTC datetime; use when you need a specific expiry time |
If both are set, max_age takes precedence in most browsers.
Flash Messages (Session-Backed)
Flash messages are stored in the session under "_flashes" and consumed once on the next request.
from flask import flash, get_flashed_messages # Write (in a view) flash("Login successful!") flash("Email is required.", "error") # Read (in a view or template) messages = get_flashed_messages() # list of strings messages = get_flashed_messages(with_categories=True) # list of (category, message)
Default category is "message" when no category is given.
Accessing Session Outside Request Context
# Push an artificial request context (tests / scripts) with app.test_request_context("/"): session["user_id"] = 1 print(session.get("user_id"))
Common Patterns
Login / Logout
@app.route("/login", methods=["POST"]) def login(): stmt = select(User).where(User.email == request.form["email"]) user = db.session.execute(stmt).scalar_one_or_none() if user and user.check_password(request.form["password"]): session.permanent = True session["user_id"] = user.id flash("Welcome back!", "success") return redirect(request.args.get("next") or url_for("dashboard")) flash("Invalid credentials.", "error") return redirect(url_for("login")) @app.route("/logout") def logout(): session.clear() flash("You have been logged out.") return redirect(url_for("index"))
Login-Required Decorator
import functools from flask import g, redirect, url_for, session def login_required(f): @functools.wraps(f) def decorated(*args, **kwargs): if "user_id" not in session: return redirect(url_for("login", next=request.url)) return f(*args, **kwargs) return decorated @app.before_request def load_user(): user_id = session.get("user_id") g.user = db.session.get(User, user_id) if user_id else None
"Remember Me" Cookie (Long-Lived)
@app.route("/login", methods=["POST"]) def login(): remember = request.form.get("remember") == "on" session.permanent = remember # PERMANENT_SESSION_LIFETIME controls duration when permanent=True session["user_id"] = user.id return redirect(url_for("dashboard"))