You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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ć

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:10:59