python
47 lines · 7 steps
Per-request SQLAlchemy sessions in Flask
A request-scoped database session that opens lazily and commits or rolls back automatically when each request ends.
Explained by
highlit
1from flask import Flask, g, jsonify, request, abort
2from sqlalchemy import create_engine
3from sqlalchemy.orm import scoped_session, sessionmaker
4
5app = Flask(__name__)
6engine = create_engine(app.config.get("DATABASE_URL", "postgresql://localhost/app"), future=True)
7SessionFactory = sessionmaker(bind=engine, autoflush=False, expire_on_commit=False)
8
9
10def get_session():
11 if "db_session" not in g:
12 g.db_session = SessionFactory()
13 return g.db_session
14
15
16@app.teardown_appcontext
17def close_session(exc):
18 session = g.pop("db_session", None)
19 if session is None:
20 return
21 if exc is None:
22 session.commit()
23 else:
24 session.rollback()
25 session.close()
26
27
28@app.post("/users")
29def create_user():
30 payload = request.get_json(silent=True) or {}
31 email = payload.get("email")
32 if not email:
33 abort(422, description="email is required")
34
35 session = get_session()
36 user = User(email=email, name=payload.get("name"))
37 session.add(user)
38 session.flush()
39 return jsonify(id=user.id, email=user.email), 201
40
41
42@app.get("/users/<int:user_id>")
43def show_user(user_id):
44 user = get_session().get(User, user_id)
45 if user is None:
46 abort(404)
47 return jsonify(id=user.id, email=user.email, name=user.name)
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Tying a session to Flask's request-scoped `g` gives each request its own isolated database connection without global state.
- 2Committing or rolling back in `teardown_appcontext` centralizes transaction handling so individual routes never manage it manually.
- 3Lazy creation via a helper means a session is only opened when a route actually touches the database.
Related explainers
python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect app = FastAPI()
Building a WebSocket chat with FastAPI
websockets
broadcast
connection-management
Intermediate
9 steps
php
<?php namespace App\Services\Checkout;
Validating coupons with Laravel's Pipeline
pipeline
chain of responsibility
transactions
Intermediate
7 steps
python
import time import uuid from django.utils.deprecation import MiddlewareMixin
Attaching per-request context in Django
middleware
request lifecycle
multi-tenancy
Intermediate
7 steps
ruby
class WeeklySignupsReport DEFAULT_WEEKS = 12 def initialize(weeks: DEFAULT_WEEKS, source: User.all)
Building a weekly signups report in Rails
service object
aggregation
group by
Intermediate
7 steps
python
import random from typing import Iterator, List
How reservoir sampling picks k items
reservoir-sampling
streaming
randomness
Intermediate
5 steps
python
import secrets from django.contrib.auth import authenticate, login from django.core.cache import cache
Two-factor login with OTP in Django
two-factor-auth
one-time-passwords
caching
Intermediate
9 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/per-request-sqlalchemy-sessions-in-flask-explained-python-072a/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.