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

Tortoise的pydantic_model_creator未生成外键字段问题排查

问题:Tortoise-ORM生成的Pydantic模型缺失ForeignKey字段

我定义了Article和Tag两个Tortoise-ORM模型,其中Article包含指向Tag的ForeignKeyField。通过自定义的get_serialize_pydantic函数(基于tortoise.contrib.pydantic.pydantic_model_creator与Pydantic的create_model生成响应模型),但最终的响应模型仅包含title和body字段,缺失了tag字段,请问这是什么原因?

相关代码

模型定义

class Tag(MyAbstractBaseModel):
    name = fields.CharField(max_length=255, index=True)

class Article(MyAbstractBaseModel):
    title = fields.CharField(max_length=255, index=True)
    body = fields.CharField(max_length=255)
    tag = fields.ForeignKeyField(model_name="Tag", related_name='article', on_delete=fields.CASCADE)

路由代码

@router.get("/article", response_model=get_serialize_pydantic(Article))
async def get():
    pass

工具函数代码

from tortoise.contrib.pydantic import pydantic_model_creator
from pydantic import BaseModel, Field, create_model

def get_serialize_pydantic(models_obj: Type[Model], exclude: Tuple[str, ...] = None):
    my_model_pydantic = pydantic_model_creator(models_obj)

    response_pydantic = create_model(
        __model_name=f"{models_obj.__name__}_response_pydantic",
        data=(Optional[List[my_model_pydantic]], Field(None, title="data")),
        __base__=BaseResponse)
    return response_pydantic

原因分析

tortoise.contrib.pydantic.pydantic_model_creator默认参数exclude_related=True,该设置会自动排除模型中所有关联字段(包括ForeignKeyField),所以生成的Article Pydantic模型里没有tag字段。

解决方案

有三种方式可以解决这个问题:

方式一:关闭关联字段默认排除

修改get_serialize_pydantic函数中生成Pydantic模型的代码,设置exclude_related=False,即可包含所有关联字段:

def get_serialize_pydantic(models_obj: Type[Model], exclude: Tuple[str, ...] = None):
    # 关闭默认的关联字段排除
    my_model_pydantic = pydantic_model_creator(models_obj, exclude_related=False)

    response_pydantic = create_model(
        __model_name=f"{models_obj.__name__}_response_pydantic",
        data=(Optional[List[my_model_pydantic]], Field(None, title="data")),
        __base__=BaseResponse)
    return response_pydantic

方式二:指定包含特定关联字段

如果只需要包含tag字段而非所有关联字段,用include参数明确指定:

def get_serialize_pydantic(models_obj: Type[Model], exclude: Tuple[str, ...] = None):
    # 仅包含tag字段
    my_model_pydantic = pydantic_model_creator(models_obj, include=("tag",))

    response_pydantic = create_model(
        __model_name=f"{models_obj.__name__}_response_pydantic",
        data=(Optional[List[my_model_pydantic]], Field(None, title="data")),
        __base__=BaseResponse)
    return response_pydantic

方式三:自定义关联字段的嵌套模型

如果需要返回tag的具体字段(而非仅ID),可以先创建Tag的Pydantic模型,再关联到Article的模型中:

def get_serialize_pydantic(models_obj: Type[Model], exclude: Tuple[str, ...] = None):
    Tag_Pydantic = pydantic_model_creator(Tag)
    # 包含tag字段并指定对应的嵌套模型
    my_model_pydantic = pydantic_model_creator(
        models_obj,
        include=("tag",),
        model_config={"relations": {"tag": {"model": Tag_Pydantic}}}
    )

    response_pydantic = create_model(
        __model_name=f"{models_obj.__name__}_response_pydantic",
        data=(Optional[List[my_model_pydantic]], Field(None, title="data")),
        __base__=BaseResponse)
    return response_pydantic

内容的提问来源于stack exchange,提问作者haojie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 13:25:47