FastAPI中如何自定义自关联模型的嵌套响应字段?
解决FastAPI分类接口返回字段冗余的方案
核心思路是通过Pydantic模型定义需要返回的字段,FastAPI会自动根据该模型序列化返回结果,过滤掉冗余字段。结合自关联模型的特性,具体步骤如下:
1. 定义Pydantic序列化模型
首先创建一个Pydantic模型,只包含你需要返回的字段,并处理自关联的子分类结构:
from pydantic import BaseModel, Optional from typing import List, ForwardRef # 处理自关联的循环引用 CategoryResponse = ForwardRef('CategoryResponse') class CategoryResponse(BaseModel): name: str slug: str order: int icon: Optional[str] = None # 适配模型中可能为null的字段 language_code: str child: Optional[List[CategoryResponse]] = [] # 自关联子分类,需与Django模型的related_name一致 class Config: orm_mode = True # 允许直接从ORM模型转换为Pydantic模型
orm_mode=True是关键配置,让Pydantic能够识别并读取Django/SQLAlchemy ORM模型的属性。- 子分类字段
child需要和你Django模型中related_name的值保持一致(如果模型里related_name是children,这里也要同步修改)。
2. 修改路由逻辑
在路由中指定response_model为上面定义的CategoryResponse,同时查询时预加载子分类字段避免性能问题:
场景1:使用SQLAlchemy连接数据库
假设你已经通过SQLAlchemy映射了Django的Category模型:
from fastapi import APIRouter, Depends from sqlalchemy.orm import Session, selectinload from database import get_db # 你的数据库会话依赖 from models import Category # SQLAlchemy映射的Category模型 router = APIRouter() @router.get("/categories/", response_model=List[CategoryResponse]) def get_all_categories(db: Session = Depends(get_db)): # 查询根分类(parent为空),并预加载子分类避免N+1查询 categories = db.query(Category)\ .filter(Category.parent.is_(None))\ .options(selectinload(Category.child))\ .all() return categories
场景2:直接使用Django ORM
如果你的FastAPI项目直接使用Django的ORM操作数据库:
from fastapi import APIRouter from myapp.models import Category # Django的Category模型 router = APIRouter() @router.get("/categories/", response_model=List[CategoryResponse]) def get_all_categories(): # 预加载子分类,提升查询性能 categories = Category.objects.filter(parent__isnull=True).prefetch_related('child') return categories
关键说明
- FastAPI会自动根据
response_model过滤字段,只返回你在Pydantic模型中定义的内容。 - 预加载子分类(
selectinload/prefetch_related)是为了避免多次查询数据库的N+1性能问题,必须加上。 - 如果需要返回多级嵌套的子分类,Pydantic会自动递归序列化,无需额外处理。
内容的提问来源于stack exchange,提问作者mirodil
相关产品推荐
相关产品推荐

