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

自定义Pydantic模型作为FastAPI的response_model时OpenAPI Schema未生成组件引用的问题咨询

自定义Pydantic模型作为FastAPI的response_model时OpenAPI Schema未生成组件引用的问题咨询

我最近在开发一个基础代码库,里面既有传统的继承自BaseModel的Pydantic模型,也有通过实现__get_pydantic_core_schema__和__get_pydantic_json_schema__来定义的自定义模型。但当我把这种自定义模型用作FastAPI路由的response_model时,生成的OpenAPI规范并没有把它作为组件模型生成引用,而是直接把结构内联在响应里了。我想知道正确使用这类自定义模型和FastAPI配合的方式是什么?

我的代码示例如下:

from pydantic_core import core_schema
from typing import Any
from fastapi.routing import APIRouter
from pydantic.json_schema import GenerateJsonSchema

router = APIRouter()

class _CustomModel:
    def __init__(self, id: int, name: str) -> None:
        self.id = id
        self.name = name

    @classmethod
    def _validate(cls, v):
        return v

    @staticmethod
    def _make_schema():
        mfs = {}
        mfs["id"] = core_schema.model_field(schema=core_schema.int_schema())
        mfs["name"] = core_schema.model_field(schema=core_schema.str_schema())
        schema = core_schema.model_fields_schema(mfs)
        return schema

    @classmethod
    def __get_pydantic_core_schema__(cls, source_type: Any, handler):
        cls._schema = _CustomModel._make_schema()
        fn = core_schema.no_info_after_validator_function(
            function=cls._validate,
            schema=cls._schema,
        )
        return fn

    @classmethod
    def __get_pydantic_json_schema__(cls, core_schema, handler):
        # TODO: here
        generator = GenerateJsonSchema()
        json_schema = generator.generate(cls._schema, mode="validation")
        return handler.resolve_ref_schema(json_schema)

@router.get(
    "/",
    summary="stub",
    response_model=_CustomModel,
)
def get_stub():
    response = _CustomModel(1, "Martin")
    return response

问题分析

你的自定义模型实现有几个关键问题导致FastAPI无法生成可复用的OpenAPI组件引用:

  1. 核心Schema类型不被识别:你在__get_pydantic_core_schema__中返回的no_info_after_validator_function属于"验证器包装器"类型,Pydantic和FastAPI不会将其识别为可复用的模型Schema,因此不会将其提取到OpenAPI的components/schemas中。

  2. JSON Schema生成逻辑绕开了默认注册流程:你直接实例化GenerateJsonSchema生成Schema,而没有使用Pydantic提供的handler来处理核心Schema,导致Pydantic无法将该Schema注册为可复用的命名组件,只能返回内联结构。


解决方案

要让自定义模型被FastAPI正确识别为可复用的Schema组件,需要调整核心Schema的定义方式和JSON Schema的处理逻辑,让Pydantic能够将其注册为命名模型:

修改后的完整代码

from pydantic_core import core_schema
from typing import Any
from fastapi.routing import APIRouter
from pydantic import GetCoreSchemaHandler, GetJsonSchemaHandler
from pydantic.json_schema import JsonSchemaValue

router = APIRouter()

class _CustomModel:
    def __init__(self, id: int, name: str) -> None:
        self.id = id
        self.name = name

    @classmethod
    def _validate(cls, v):
        # 处理两种场景:直接传入模型实例,或传入字典(FastAPI序列化/反序列化时)
        if isinstance(v, dict):
            return cls(v["id"], v["name"])
        return v

    @classmethod
    def __get_pydantic_core_schema__(
        cls, source_type: Any, handler: GetCoreSchemaHandler
    ) -> core_schema.CoreSchema:
        # 使用core_schema.model定义标准模型Schema,标记为可命名组件
        model_core_schema = core_schema.model(
            fields={
                "id": core_schema.int_schema(),
                "name": core_schema.str_schema(),
            },
            # 指定模型的显示名称,会出现在OpenAPI components/schemas中
            metadata={"title": "CustomModel"}
        )
        
        # 用验证器包装模型Schema,确保输入被转换为_CustomModel实例
        return core_schema.no_info_after_validator_function(
            function=cls._validate,
            schema=model_core_schema,
        )

    @classmethod
    def __get_pydantic_json_schema__(
        cls, core_schema_: core_schema.CoreSchema, handler: GetJsonSchemaHandler
    ) -> JsonSchemaValue:
        # 让Pydantic的默认handler处理核心Schema,自动完成组件注册
        json_schema = handler(core_schema_)
        # 自定义模型的显示名称(可选,若metadata中已指定title可省略)
        json_schema["title"] = "CustomModel"
        # 解析为引用Schema,而不是内联结构
        return handler.resolve_ref_schema(json_schema)

@router.get(
    "/",
    summary="stub",
    response_model=_CustomModel,
)
def get_stub():
    response = _CustomModel(1, "Martin")
    return response

关键修改点说明

  1. 使用core_schema.model定义核心Schema:
    这是Pydantic推荐的模型Schema定义方式,会被识别为可复用的命名模型类型。通过metadata={"title": "CustomModel"}指定的名称,会直接作为OpenAPI组件的键名。

  2. 优化验证逻辑:
    调整_validate方法,处理字典输入的场景(比如FastAPI在序列化响应时会将模型实例转为字典,再验证回模型类型),确保类型转换的完整性。

  3. 依赖Pydantic的默认JSON Schema处理流程:
    在__get_pydantic_json_schema__中直接调用handler(core_schema_),让Pydantic的默认逻辑处理Schema生成和组件注册,再通过handler.resolve_ref_schema返回引用,而不是内联结构。

  4. 使用标准类型提示:
    引入GetCoreSchemaHandler和GetJsonSchemaHandler类型,让代码更符合Pydantic的规范,同时获得更好的类型检查支持。


验证效果

启动FastAPI应用后,访问/docs或/redoc,你会看到OpenAPI规范的components/schemas中出现了CustomModel,而路由的响应Schema会通过{"$ref": "#/components/schemas/CustomModel"}引用该组件,不再是内联的结构。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 07:43:03