Flask REST APIs & JSON
π REST method conventions
| Method | Meaning | Example |
|---|---|---|
| GET | retrieve | GET /api/users |
| POST | create | POST /api/users |
| PUT | replace entirely | PUT /api/users/42 |
| PATCH | partial update | PATCH /api/users/42 |
| DELETE | remove | DELETE /api/users/42 |
ποΈ Basic CRUD
from flask import jsonify, request, abort
@app.route("/api/users", methods=["GET"])
def get_users():
return jsonify(users)
@app.route("/api/users/<int:user_id>", methods=["GET"])
def get_user(user_id):
user = next((u for u in users if u["id"] == user_id), None)
if user is None:
abort(404)
return jsonify(user)
@app.route("/api/users", methods=["POST"])
def create_user():
data = request.get_json()
if not data or "name" not in data:
return jsonify({"error": "name required"}), 400
new_user = {"id": len(users)+1, "name": data["name"]}
users.append(new_user)
return jsonify(new_user), 201 # 201 = Created, return the new resource
@app.route("/api/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
global users
users = [u for u in users if u["id"] != user_id]
return "", 204 # 204 = No ContentποΈ With SQLAlchemy model
@app.route("/api/users/<int:user_id>")
def get_user(user_id):
user = User.query.get_or_404(user_id)
return jsonify(user.to_dict())
class User(db.Model):
def to_dict(self):
return {"id": self.id, "username": self.username, "email": self.email}
to_dict()on the model = control exactly what's exposed (keep password_hash out).
π Marshmallow (structured serialization, bigger APIs)
pip install flask-marshmallow marshmallow-sqlalchemyfrom flask_marshmallow import Marshmallow
ma = Marshmallow(app)
class UserSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = User
load_instance = True
users_schema = UserSchema(many=True)
return jsonify(users_schema.dump(users))π Token auth
from functools import wraps
def require_api_key(f):
@wraps(f)
def wrapper(*a, **kw):
if request.headers.get("X-API-Key") != "expected-key":
return jsonify({"error": "Invalid API key"}), 401
return f(*a, **kw)
return wrapper
@app.route("/api/protected")
@require_api_key
def protected():
return jsonify({"message": "access granted"})Real production APIs typically use JWT (
flask-jwt-extended) instead of a shared key.
π CORS
pip install flask-corsfrom flask_cors import CORS
CORS(app) # any origin β dev only
CORS(app, origins=["https://myfrontend.com"]) # restricted β productionπ Next
Flask Error Handling & Logging Β· Flask Testing & Deployment