作者:张大鹏 时间:2025 年 11 月 标签:FastAPI / SQLAlchemy / FastCRUD / 后端开发 / REST API
一、引言
在 FastAPI 项目中,我们通常会手写大量重复的 CRUD 逻辑(Create / Read / Update / Delete)。 例如,一个博客系统的后台往往包括:
- 用户表(Users)
- 文章表(Posts)
- 评论表(Comments)
而每个模型都需要相似的增删改查接口。 这会导致重复的模板式代码 ------ 不仅冗余,还容易出错。
于是,我们引入一个强大的自动化工具:FastCRUD。
FastCRUD 是一个基于 FastAPI + SQLAlchemy 2.0 的开源库,可以:
- 🔧 自动生成 CRUD 路由(无需手写重复接口)
- ⚡ 全异步支持(AsyncSession + async engine)
- 🔍 内建分页、排序、关联查询(join)
- 🧩 与 Pydantic 2.x 完美集成
下面我们将用它一步步构建一个简洁高效的博客后端 API。
二、项目结构设计
我们将构建以下结构:
bash
fastcrud_blog/
│
├── main.py # FastAPI 启动入口
├── database.py # 数据库配置(engine, session)
├── models.py # SQLAlchemy ORM 模型
├── schemas.py # Pydantic 模型
├── routers/
│ ├── users.py
│ ├── posts.py
│ └── comments.py
└── requirements.txt
环境要求:
bash
Python >= 3.9
FastAPI >= 0.110
SQLAlchemy >= 2.0
FastCRUD >= 0.1.4
安装依赖:
bash
pip install fastapi[all] sqlalchemy fastcrud pydantic
三、配置数据库
文件:database.py
python
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite+aiosqlite:///./blog.db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_session() -> AsyncSession:
async with async_session() as session:
yield session
四、定义数据模型
文件:models.py
python
from sqlalchemy.orm import DeclarativeBase, relationship
from sqlalchemy import Column, Integer, String, Text, ForeignKey
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(50), unique=True, index=True)
email = Column(String(100), unique=True)
posts = relationship("Post", back_populates="author")
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True)
title = Column(String(200))
content = Column(Text)
author_id = Column(Integer, ForeignKey("users.id"))
author = relationship("User", back_populates="posts")
comments = relationship("Comment", back_populates="post")
class Comment(Base):
__tablename__ = "comments"
id = Column(Integer, primary_key=True)
content = Column(Text)
post_id = Column(Integer, ForeignKey("posts.id"))
post = relationship("Post", back_populates="comments")
五、定义 Schema(Pydantic 模型)
文件:schemas.py
python
from pydantic import BaseModel
from typing import Optional
# User Schemas
class UserBase(BaseModel):
username: str
email: str
class UserCreate(UserBase):
pass
class UserUpdate(BaseModel):
email: Optional[str] = None
# Post Schemas
class PostBase(BaseModel):
title: str
content: str
class PostCreate(PostBase):
author_id: int
class PostUpdate(BaseModel):
title: Optional[str]
content: Optional[str]
# Comment Schemas
class CommentBase(BaseModel):
content: str
class CommentCreate(CommentBase):
post_id: int
class CommentUpdate(BaseModel):
content: Optional[str]
六、使用 FastCRUD 自动生成 CRUD 路由
6.1 用户接口
文件:routers/users.py
python
from fastapi import APIRouter
from fastcrud import crud_router
from models import User
from schemas import UserCreate, UserUpdate
from database import get_session
user_router = crud_router(
session=get_session,
model=User,
create_schema=UserCreate,
update_schema=UserUpdate,
path="/users",
tags=["Users"]
)
6.2 文章接口
文件:routers/posts.py
python
from fastcrud import crud_router
from models import Post
from schemas import PostCreate, PostUpdate
from database import get_session
post_router = crud_router(
session=get_session,
model=Post,
create_schema=PostCreate,
update_schema=PostUpdate,
path="/posts",
tags=["Posts"]
)
6.3 评论接口
文件:routers/comments.py
python
from fastcrud import crud_router
from models import Comment
from schemas import CommentCreate, CommentUpdate
from database import get_session
comment_router = crud_router(
session=get_session,
model=Comment,
create_schema=CommentCreate,
update_schema=CommentUpdate,
path="/comments",
tags=["Comments"]
)
七、整合主应用
文件:main.py
python
from fastapi import FastAPI
from models import Base
from database import engine
from routers.users import user_router
from routers.posts import post_router
from routers.comments import comment_router
app = FastAPI(title="FastCRUD Blog API")
@app.on_event("startup")
async def init_db():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
app.include_router(user_router)
app.include_router(post_router)
app.include_router(comment_router)
启动服务:
bash
uvicorn main:app --reload
打开浏览器访问:
👉 http://127.0.0.1:8000/docs
你将看到自动生成的接口文档,包括:
POST /users/创建用户GET /users/{id}获取用户详情POST /posts/发布文章GET /comments/查看评论
FastCRUD 自动帮你生成了完整的 CRUD 逻辑、路径和 Pydantic 校验。
八、分页、排序与 Join
FastCRUD 的查询接口支持高级参数,例如:
python
from fastcrud import FastCRUD
from models import Post
from database import get_session
from schemas import PostCreate
post_crud = FastCRUD(Post)
@app.get("/posts/paginated")
async def list_posts(limit: int = 10, offset: int = 0, db=Depends(get_session)):
return await post_crud.get_multi(db, limit=limit, offset=offset, sort_columns=["id"], sort_orders=["desc"])
支持 offset、cursor 分页与多字段排序,常用于后台文章列表或时间线接口。
九、扩展:加入权限验证
你可以在自动生成的路由外层包一层依赖注入。例如:
python
from fastapi import Depends, HTTPException
from fastcrud import crud_router
from dependencies import get_current_user # 你自己定义的 JWT 验证逻辑
post_router = crud_router(
session=get_session,
model=Post,
create_schema=PostCreate,
update_schema=PostUpdate,
path="/posts",
tags=["Posts"],
dependencies=[Depends(get_current_user)]
)
这样,所有 /posts/* 路径都将自动启用 JWT 验证。
十、总结与实践建议
| 优点 | 说明 |
|---|---|
| 🚀 高开发效率 | 自动生成 CRUD 端点,几乎不用手写基础逻辑 |
| ⚙️ 异步性能优秀 | 完美契合 FastAPI 异步架构 |
| 🧠 可扩展性强 | 可组合 FastCRUD 与自定义逻辑 |
| 📦 易于维护 | 统一 CRUD 模板、简化项目结构 |
适用场景:
- 博客系统、管理后台、CMS、企业内部 API
- 原型验证期快速上线
- 需要标准化 CRUD 的微服务架构
十一、结语
使用 FastCRUD 开发博客 API,可以让你在几分钟内完成整个后端骨架。 它让我们从繁琐的 CRUD 模板代码中解放出来,专注于业务逻辑与架构设计。
如果你想继续深入,可以考虑在 FastCRUD 基础上:
- 加入用户权限体系(JWT / OAuth2)
- 实现软删除、审计字段(created_at / updated_at)
- 编写自定义查询(如"某用户的热门文章列表")