4. 响应模型与字段过滤
任务说明
本案例要求使用 FastAPI 与 Pydantic 完成一个最小可用的用户注册接口:客户端通过 POST /users 提交 JSON 请求体,服务端使用 Pydantic 模型自动完成字段类型校验、必填校验与约束校验,校验通过后返回创建成功的用户信息(含服务端生成的 id)。
核心实现
# main.py
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, EmailStr, Field
from typing import Optional
app = FastAPI()
class UserCreate(BaseModel):
"""请求体模型:定义客户端必须提交的字段及校验规则"""
username: str = Field(..., min_length=3, max_length=20, description="用户名,3-20个字符")
email: EmailStr = Field(..., description="合法邮箱地址")
age: Optional[int] = Field(None, ge=18, le=100, description="年龄,18-100之间(可选)")
class UserResponse(BaseModel):
"""响应模型:返回给客户端的数据结构"""
id: int
username: str
email: EmailStr
age: Optional[int] = None
# 模拟数据库存储(仅用于演示,实际项目应使用真实数据库)
users_db = {}
user_id_counter = 1
@app.post("/users", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def create_user(user: UserCreate):
"""
接收请求体,Pydantic 自动完成类型转换与校验。
校验失败时 FastAPI 自动返回 422 错误及详细原因。
"""
global user_id_counter
# 检查用户名是否已存在(业务校验)
if any(u["username"] == user.username for u in users_db.values()):
raise HTTPException(status_code=400, detail="用户名已存在")
# 生成新用户数据
new_user = {
"id": user_id_counter,
"username": user.username,
"email": user.email,
"age": user.age,
}
users_db[user_id_counter] = new_user
user_id_counter += 1
return new_user
代码说明
上述代码中,UserCreate 模型定义了请求体结构:username 为必填字符串且长度限制在 3~20 字符;email 使用 EmailStr 类型自动验证邮箱格式;age 为可选整数,若提供则必须在 18~100 之间。FastAPI 在路由处理函数中将 user: UserCreate 作为参数声明,即自动从请求 JSON 中解析并校验数据。校验失败时,FastAPI 自动返回 422 Unprocessable Entity,响应体中包含具体错误字段与原因。校验通过后,函数内部执行用户名唯一性检查(业务规则),通过后生成新用户记录并返回。
接口报文结构
运行与验证
- 安装依赖:
pip install fastapi uvicorn pydantic[email] - 启动服务:
uvicorn main:app --reload --port 8000 - 发送合法请求(预期返回 201 与用户数据):
curl -X POST http://127.0.0.1:8000/users \
-H "Content-Type: application/json" \
-d '{"username": "alice", "email": "alice@example.com", "age": 25}'
预期输出(与代码逻辑一致):{"id":1,"username":"alice","email":"alice@example.com","age":25}
- 发送非法请求(邮箱格式错误,预期返回 422):
curl -X POST http://127.0.0.1:8000/users \
-H "Content-Type: application/json" \
-d '{"username": "alice", "email": "not-an-email", "age": 25}'
预期输出:HTTP 422,响应体包含 email 字段的校验错误详情。
判定标准
- 合法请求返回
201状态码,响应体包含服务端生成的id字段; - 缺少必填字段、邮箱格式错误、用户名长度不足或 age 超出范围时,均返回
422且错误信息指明具体字段; - 重复提交相同用户名返回
400与错误提示“用户名已存在”。