8.4 数据库会话中间件
FastAPI Database Session Middleware Tutorial for Python Beginners
A beginner-friendly guide to using database session middleware in FastAPI. Learn step-by-step with simple examples, analogies, and hands-on practice to build your first web app confidently.
FastAPI Database Session Middleware Tutorial for Python Beginners
Welcome! If you know basic Python but have never built a web app, you're in the right place. This tutorial will guide you through using database session middleware in FastAPI with simple, fun examples. We'll focus on doing, not just reading, so get ready to see your code come to life!
What is FastAPI?
FastAPI is a modern web framework for building APIs with Python. Think of it as a super-efficient assistant that helps your Python code talk to the internet—like a translator between your app and users' browsers or apps.
What is Database Session Middleware?
Imagine you're at a restaurant. A database is like the kitchen's storage of ingredients, and a session is your table where you place orders and eat. Middleware is the waiter who manages your table session, ensuring everything runs smoothly without you having to worry about it. In FastAPI, database session middleware helps handle connections to your database for each request, making it easy to store and retrieve data.
Let's dive in and build something together!
Step 1: Set Up Your Environment
First, you'll need Python installed (version 3.7 or above). Open your terminal or command prompt and install FastAPI and other tools.
Run these commands:
pip install fastapi uvicorn sqlalchemy databases[postgresql]
fastapi: The framework itself.uvicorn: A server to run your app.sqlalchemyanddatabases: Libraries for database operations. We'll use PostgreSQL for this example, but you can adapt it to other databases.
Success Moment: No errors? Great! You've set up your tools.
Step 2: Create Your First FastAPI App
Let's start simple to build confidence. Create a file named main.py and add this code:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
Save the file. In your terminal, run:
uvicorn main:app --reload
Open your browser and go to http://127.0.0.1:8000. You should see {"Hello": "World"}.
Success Moment: Your first FastAPI app is live! This proves everything is working.
Step 3: Understand Databases with an Analogy
Think of a database as a digital filing cabinet. In this tutorial, we'll use PostgreSQL—a popular filing cabinet that's easy to set up. If you don't have PostgreSQL, you can use a simple in-memory database for practice, but let's simulate a real scenario.
We'll create a simple app to manage a list of books.
Step 4: Add a Database Connection
Update main.py to include database setup. We'll use SQLAlchemy to define our data and databases for async support.
First, let's install a database driver for PostgreSQL (skip if using another database):
pip install asyncpg
Now, add this to main.py:
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
import databases
# Database URL - change this to your PostgreSQL connection string
DATABASE_URL = "postgresql://user:password@localhost/dbname"
# For practice, you can use an in-memory SQLite database:
# DATABASE_URL = "sqlite:///./test.db"
# Set up database
database = databases.Database(DATABASE_URL)
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# Define a simple Book model
class Book(Base):
__tablename__ = "books"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
author = Column(String)
# Create tables in the database
Base.metadata.create_all(bind=engine)
app = FastAPI()
# Startup event to connect database
@app.on_event("startup")
async def startup():
await database.connect()
# Shutdown event to disconnect database
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()
# Dependency to get database session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/")
def read_root():
return {"Hello": "World"}
Explanation:
- We define a
Bookclass to represent data in the database. SessionLocalcreates session instances for each request.- The
get_dbfunction is our middleware—it provides a database session to our endpoints.
Step 5: Use Session Middleware in Endpoints
Now, let's add an endpoint to create a book and see the session in action. Update main.py:
from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel
from typing import List
# Pydantic model for request/response
class BookCreate(BaseModel):
title: str
author: str
class BookResponse(BaseModel):
id: int
title: str
author: str
# Endpoint to create a book
@app.post("/books/", response_model=BookResponse)
def create_book(book: BookCreate, db: Session = Depends(get_db)):
db_book = Book(title=book.title, author=book.author)
db.add(db_book)
db.commit()
db.refresh(db_book)
return db_book
# Endpoint to list all books
@app.get("/books/", response_model=List[BookResponse])
def read_books(db: Session = Depends(get_db)):
books = db.query(Book).all()
return books
How It Works:
- When a request comes in (e.g., to create a book), FastAPI calls
get_db()to get a database session. - This session is used in the endpoint to interact with the database.
- The session is automatically closed after the request, thanks to the
finallyblock inget_db.
Success Moment: Let's test it! Run the app with uvicorn main:app --reload. Use a tool like curl or an API client (e.g., Postman or browser extensions) to send requests.
-
Create a book:
- Method: POST
- URL:
http://127.0.0.1:8000/books/ - Body (JSON):
{"title": "Python for Beginners", "author": "John Doe"} - You should get a response like
{"id": 1, "title": "Python for Beginners", "author": "John Doe"}.
-
List books:
- Method: GET
- URL:
http://127.0.0.1:8000/books/ - You should see the book you just created in a list.
Congratulations! You've successfully used database session middleware to handle data in FastAPI. This is a big step—you've built a functional web app that stores and retrieves information.
Step 6: More Examples for Confidence
Let's add update and delete operations to complete a simple CRUD (Create, Read, Update, Delete) app.
Add to main.py:
# Endpoint to update a book
@app.put("/books/{book_id}", response_model=BookResponse)
def update_book(book_id: int, book: BookCreate, db: Session = Depends(get_db)):
db_book = db.query(Book).filter(Book.id == book_id).first()
if db_book is None:
raise HTTPException(status_code=404, detail="Book not found")
db_book.title = book.title
db_book.author = book.author
db.commit()
db.refresh(db_book)
return db_book
# Endpoint to delete a book
@app.delete("/books/{book_id}")
def delete_book(book_id: int, db: Session = Depends(get_db)):
db_book = db.query(Book).filter(Book.id == book_id).first()
if db_book is None:
raise HTTPException(status_code=404, detail="Book not found")
db.delete(db_book)
db.commit()
return {"message": "Book deleted"}
Test these endpoints:
- Update: PUT to
http://127.0.0.1:8000/books/1with a new title and author. - Delete: DELETE to
http://127.0.0.1:8000/books/1.
Each time, the session middleware ensures the database interaction is handled smoothly.
Recap and Next Steps
In this tutorial, you've learned:
- What FastAPI and database session middleware are, using a restaurant analogy.
- How to set up a FastAPI app with a database.
- How to implement session middleware to manage database connections.
- Built a simple book management app with CRUD operations, experiencing multiple "success moments."
To go further:
- Explore FastAPI documentation for more features.
- Try adding error handling or authentication.
- Practice with different database types.
Remember, every expert was once a beginner. Keep building, and you'll gain more confidence!
Final Success Moment: You now have a working web app that uses database session middleware. Share it with friends or expand it into a personal project!
Happy coding! 🚀