python
47 lines · 7 steps
Versioning a Flask API with Blueprints
Two Blueprints let v1 and v2 of a users endpoint coexist under separate URL prefixes.
Explained by
highlit
1from flask import Blueprint, jsonify, request, abort
2
3v1 = Blueprint("users_v1", __name__)
4v2 = Blueprint("users_v2", __name__)
5
6
7@v1.route("/users/<int:user_id>")
8def get_user_v1(user_id):
9 user = User.query.get_or_404(user_id)
10 return jsonify({
11 "id": user.id,
12 "name": f"{user.first_name} {user.last_name}",
13 "email": user.email,
14 })
15
16
17@v2.route("/users/<int:user_id>")
18def get_user_v2(user_id):
19 user = User.query.get_or_404(user_id)
20 return jsonify({
21 "id": user.id,
22 "first_name": user.first_name,
23 "last_name": user.last_name,
24 "email": user.email,
25 "links": {
26 "self": f"/v2/users/{user.id}",
27 "orders": f"/v2/users/{user.id}/orders",
28 },
29 })
30
31
32@v2.route("/users", methods=["POST"])
33def create_user_v2():
34 payload = request.get_json(silent=True) or {}
35 if not payload.get("email"):
36 abort(422, description="email is required")
37 user = User.create(
38 first_name=payload.get("first_name", ""),
39 last_name=payload.get("last_name", ""),
40 email=payload["email"],
41 )
42 return jsonify({"id": user.id, "email": user.email}), 201
43
44
45def register_api(app):
46 app.register_blueprint(v1, url_prefix="/v1")
47 app.register_blueprint(v2, url_prefix="/v2")
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Separate Blueprints let you ship a new API version without breaking the old one.
- 2Mounting Blueprints under url_prefix keeps versioned routes cleanly namespaced.
- 3Changing a response shape between versions is safe when each version owns its own handler.
Related explainers
python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect app = FastAPI()
Building a WebSocket chat with FastAPI
websockets
broadcast
connection-management
Intermediate
9 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
rust
use axum::{ extract::{Path, State}, response::sse::{Event, KeepAlive, Sse}, };
Streaming import progress with SSE in Axum
server-sent-events
streams
watch-channel
Advanced
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
python
import re from functools import total_ordering from typing import Optional
Parsing and comparing semantic versions
regex
operator-overloading
sorting
Intermediate
7 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/versioning-a-flask-api-with-blueprints-explained-python-996a/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.