技术分享FastAPIPydantic入门教程
我的第一个FastAPI项目:从小白到跑通API
2025/8/1710 min77 次观看
手把手带你搭建FastAPI项目骨架,Pydantic真香警告
01 写在前面
终于开始学FastAPI了!之前用Flask写过小项目,这次要挑战一下更现代的框架。
本文记录我的第一个FastAPI项目是如何搭建的,以及遇到的那些坑。
02 项目初始化
按照国际惯例,先创项目结构:
mkdir -p blog_api/app/{api/v1,schemas,models,services,db,core}
cd blog_api
pip install fastapi uvicorn pydantic-settings
目录结构是这样的:
blog_api/
├── app/
│ ├── main.py # 应用入口
│ ├── config.py # 配置管理
│ ├── api/v1/ # 路由
│ ├── schemas/ # Pydantic模型
│ ├── models/ # ORM模型
│ └── services/ # 业务逻辑
├── .env
└── requirements.txt
03 配置管理
学到的第一件事:用pydantic-settings管理配置,告别硬编码:
# app/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "BlogAPI"
debug: bool = True
database_url: str = "postgresql+asyncpg://postgres:postgres@localhost:5432/blog_db"
redis_url: str = "redis://localhost:6379/0"
secret_key: str = "change-this-in-production"
model_config = {"env_file": ".env"}
settings = Settings()
# .env
APP_NAME=BlogAPI
DEBUG=true
SECRET_KEY=my-secret-key-123
DATABASE_URL=postgresql+asyncpg://...
04 Pydantic也太香了吧
之前用Flask,参数验证要自己写一堆if判断。用Pydantic,定义好模型就行:
# app/schemas/post.py
from pydantic import BaseModel, Field
from datetime import datetime
from enum import Enum
class PostStatus(str, Enum):
draft = "draft"
published = "published"
class PostCreate(BaseModel):
"""创建文章的请求体验证"""
title: str = Field(..., min_length=1, max_length=200)
content: str = Field(..., min_length=1)
category_id: int | None = None
status: PostStatus = PostStatus.draft
class PostOut(BaseModel):
"""文章响应模型"""
id: int
title: str
content: str
status: PostStatus
category_id: int | None
author_id: int
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True} # 从ORM模型读取
Field参数超好用:
...表示必填min_length/max_length字符串限制ge/le数字限制description自动生成文档
05 第一个API
写个最简单的文章CRUD:
# app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.v1.router import router as api_router
app = FastAPI(title="BlogAPI", version="1.0")
# CORS跨域配置
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router, prefix="/api/v1")
@app.get("/")
async def root():
return {"message": "BlogAPI is running"}
# app/api/v1/posts.py
from fastapi import APIRouter, HTTPException
from app.schemas.post import PostCreate, PostOut
router = APIRouter(prefix="/posts", tags=["posts"])
# 内存存储(后续会接入数据库)
posts = []
@router.post("/", response_model=PostOut, status_code=201)
async def create_post(data: PostCreate):
post = {
"id": len(posts) + 1,
**data.model_dump(),
"author_id": 1,
"created_at": "2024-01-01T00:00:00",
"updated_at": "2024-01-01T00:00:00",
}
posts.append(post)
return post
@router.get("/")
async def list_posts():
return posts
@router.get("/{post_id}")
async def get_post(post_id: int):
for post in posts:
if post["id"] == post_id:
return post
raise HTTPException(status_code=404, detail="文章不存在")
06 启动项目
uvicorn app.main:app --reload
访问 http://127.0.0.1:8000/docs,Swagger UI 自动生成!
07 总结
- pydantic-settings 管理配置,代码整洁
- Pydantic 自动验证参数,自动生成文档
- response_model 过滤返回字段,保证数据安全
- FastAPI自动生成Swagger,接入方狂喜