FastAPI中继承CBV类时如何重写路由并生效?
FastAPI CBV子类重写端点却执行父类方法的解决方案
问题描述
使用@cbv装饰器搭配InferringRouter实现CRUD操作的父类,创建子类继承该父类并重写部分端点方法后,Swagger UI能显示重写方法的参数,但实际发起请求时却执行父类的方法。
问题代码示例
from fastapi.responses import JSONResponse from fastapi_utils.cbv import cbv from fastapi_utils.inferring_router import InferringRouter from .student import Student as ParentClass, router as parent_router # remaining imports for pydantic models router = InferringRouter(routes=parent_router.routes) @cbv(router) class StudentService(ParentClass): def __init__(self, request: Request): super().__init__(request) @router.get( "/list", summary="", description="", response_model_exclude_none=True, responses=errors(UnauthorizedError), response_class=JSONResponse, response_model=ListResponse[Student], response_model_by_alias=False ) def get_list(self, diff_parameter:str = Query('str', description='Different parameter')) -> List[Student]: pass #code for getting list of students, now overridden
解决方案
1. 不要直接继承父类路由
当前代码中router = InferringRouter(routes=parent_router.routes)直接复制了父类的路由条目,导致父类的/list端点仍然存在。FastAPI会优先匹配先注册的端点,所以请求会走到父类方法。正确做法是创建全新的路由实例:
# 替换原有路由创建方式,不要继承父类routes router = InferringRouter()
2. 将路由装饰器移到类内部
你把@router.get放在了类外部,这会导致方法无法正确绑定到StudentService子类实例上。必须将路由装饰器放在类内部的重写方法上方,和父类的写法保持一致。
3. 修正后的完整代码
from fastapi.responses import JSONResponse from fastapi_utils.cbv import cbv from fastapi_utils.inferring_router import InferringRouter from fastapi import Request, Query from .student import Student as ParentClass from typing import List # 导入你的pydantic模型及错误处理工具 # 创建全新路由,不继承父类路由条目 router = InferringRouter() @cbv(router) class StudentService(ParentClass): def __init__(self, request: Request): super().__init__(request) # 将路由装饰器放在类内部方法上方,绑定到子类实例 @router.get( "/list", summary="", description="", response_model_exclude_none=True, responses=errors(UnauthorizedError), response_class=JSONResponse, response_model=ListResponse[Student], response_model_by_alias=False ) def get_list(self, diff_parameter: str = Query('str', description='Different parameter')) -> List[Student]: # 这里编写你的重写逻辑 # 示例返回: return [Student(name="张三", age=20)]
核心原因说明
- FastAPI的CBV通过
@cbv装饰器将类与路由绑定,类内部的方法通过路由装饰器注册时,会自动关联类的实例。如果装饰器放在类外部,方法无法关联到子类实例,调用时会沿用父类的绑定逻辑。 - 复制父类路由会导致同一路径存在两个端点(父类和子类),FastAPI按注册顺序匹配,优先执行父类方法。
内容的提问来源于stack exchange,提问作者Mihailo Jakovljević
相关产品推荐
相关产品推荐

