Pydantic serialisation 中文文档(完整版)


前言

初衷:在学习的时候发现 Tortoise-ORM FastAPI integration 官方文档缺中文版,翻阅英文文档效率低,萌生翻译想法。
本系列旨在原汁原味的翻译 Tortoise-ORM FastAPI integration 官方文档,帮助英语不好的小伙伴快速学习使用方法。
翻译不易,禁止商业用途,转载请标明出处,具体情况或反馈请联系作者`。
如果觉得翻译不错,欢迎在文章底部请博主喝杯奶茶,您的鼓励就是俺最大的动力!😄

简介

Tortoise ORM 提供 Pydantic 插件,可以从 Tortoise Models 生成 Pydantic 模型,然后提供辅助函数来序列化该模型及其相关对象。

我们目前仅支持为序列化生成 Pydantic 对象,目前尚不支持反序列化。

具体参考Pydantic Examples

教程

基础用法

这里我们将介绍:

  • 从 Tortoise 模型创建一个 Pydantic 模型
  • 使用文档字符串和文档注释
  • 评估生成的 schema
  • 使用 .model_dump().model_dump_json() 函数进行简单序列化

官方示例直通车

让我们从一个基础的 Tortoise 模型开始:

from tortoise import fields
from tortoise.models import Model

class Tournament(Model):
    """
    This references a Tournament
    """
    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=100)
    #: The date-time the Tournament record was created at
    created_at = fields.DatetimeField(auto_now_add=True)

要从中创建一个 Pydantic 模型,就需要调用该函数:tortoise.contrib.pydantic.creator.pydantic_model_creator()

from tortoise.contrib.pydantic import pydantic_model_creator

Tournament_Pydantic = pydantic_model_creator(Tournament)

现在我们有了一个 Pydantic 模型,可以用来定义 schema 数据模式并实现序列化功能。

如下代码是 Tournament_Pydantic 模型的 JSON-Schema :

>>> print(Tournament_Pydantic.schema())
{
    'title': 'Tournament',
    'description': 'This references a Tournament',
    'type': 'object',
    'properties': {
        'id': {
            'title': 'Id',
            'type': 'integer'
        },
        'name': {
            'title': 'Name',
            'type': 'string'
        },
        'created_at': {
            'title': 'Created At',
            'description': 'The date-time the Tournament record was created at',
            'type': 'string',
            'format': 'date-time'
        }
    }
}

注意现在关于 Schema的描述内包含了类的文档字符串和文档注释 #:

序列化对象,只需(在异步环境中)进行以下操作:

tournament = await Tournament.create(name="New Tournament")
tourpy = await Tournament_Pydantic.from_tortoise_orm(tournament)

现在我们获取数据库内容只需要使用常规的 Pydantic-object 方法, 例如 .model_dump() 或 .model_dump_json()

>>> print(tourpy.model_dump())
{
    'id': 1,
    'name': 'New Tournament',
    'created_at': datetime.datetime(2020, 3, 1, 20, 28, 9, 346808)
}
>>> print(tourpy.model_dump_json())
{
    "id": 1,
    "name": "New Tournament",
    "created_at": "2020-03-01T20:28:09.346808"
}

查询集与列表

这里我们将介绍:

  • 创建一个列表模型来序列化一个查询集
  • 遵循默认的排序方式

官方示例直通车

from tortoise import fields
from tortoise.models import Model

class Tournament(Model):
    """
    This references a Tournament
    """
    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=100)
    #: The date-time the Tournament record was created at
    created_at = fields.DatetimeField(auto_now_add=True)

    class Meta:
        # Define the default ordering
        #  the pydantic serialiser will use this to order the results
        ordering = ["name"]

要从中创建一个 Pydantic 列表模型,就需要调用该函数:tortoise.contrib.pydantic.creator.pydantic_queryset_creator()

from tortoise.contrib.pydantic import pydantic_queryset_creator

Tournament_Pydantic_List = pydantic_queryset_creator(Tournament)

现在我们有一个 Pydantic 模型,可以用来定义 schema 数据模式并实现序列化功能。

如下代码是 Tournament_Pydantic_List 模型的 JSON-Schema :

>>> print(Tournament_Pydantic_List.schema())
{
    'title': 'Tournaments',
    'description': 'This references a Tournament',
    'type': 'array',
    'items': {
        '$ref': '#/definitions/Tournament'
    },
    'definitions': {
        'Tournament': {
            'title': 'Tournament',
            'description': 'This references a Tournament',
            'type': 'object',
            'properties': {
                'id': {
                    'title': 'Id',
                    'type': 'integer'
                },
                'name': {
                    'title': 'Name',
                    'type': 'string'
                },
                'created_at': {
                    'title': 'Created At',
                    'description': 'The date-time the Tournament record was created at',
                    'type': 'string',
                    'format': 'date-time'
                }
            }
        }
    }
}

注意现在 Tournament 不再是根节点了。取而代之的是一个简单的列表,即 Tournament_Pydantic_List

序列化对象,只需(在异步环境中)进行以下操作:

# Create objects
await Tournament.create(name="New Tournament")
await Tournament.create(name="Another")
await Tournament.create(name="Last Tournament")

tourpy = await Tournament_Pydantic_List.from_queryset(Tournament.all())

现在我们获取数据库内容只需要使用常规的 Pydantic-object 方法, 例如 .model_dump() 或 .model_dump_json()

>>> print(tourpy.model_dump())
{
    'root': [
        {
            'id': 2,
            'name': 'Another',
            'created_at': datetime.datetime(2020, 3, 2, 6, 53, 39, 776504)
        },
        {
            'id': 3,
            'name': 'Last Tournament',
            'created_at': datetime.datetime(2020, 3, 2, 6, 53, 39, 776848)
        },
        {
            'id': 1,
            'name': 'New Tournament',
            'created_at': datetime.datetime(2020, 3, 2, 6, 53, 39, 776211)
        }
    ]
}
>>> print(tourpy.model_dump_json())
[
    {
        "id": 2,
        "name": "Another",
        "created_at": "2020-03-02T06:53:39.776504"
    },
    {
        "id": 3,
        "name": "Last Tournament",
        "created_at": "2020-03-02T06:53:39.776848"
    },
    {
        "id": 1,
        "name": "New Tournament",
        "created_at": "2020-03-02T06:53:39.776211"
    }
]

请注意,.model_dump() 方法具有一个包含列表的根元素,而 .model_dump_json() 方法将列表作为根节点。同时还要注意结果(名称)按字母顺序排序。

表之间的关系与早期模型初始化

这里我们将介绍:

  • 表之间的关系
  • 早期模型初始化

关于早期初始化(early-init)的这一部分操作仅在你需要在初始化 Tortoise ORM 之前创建 Pydantic 模型时才需要。
请仔细看 Basic Pydantic (在函数 run 中),可以看到 *_creator 是在我们正确初始化 Tortoise ORM 之后调用的,在这种情况下,就可以避免不必要的操作,即不需要提前初始化。

简单来说:如果你在使用 Tortoise ORM 之前就需要创建一些 pydantic 数据模型,就需要进行早期初始化;但如果你可以在初始化完 Tortoise ORM 之后再创建这些模型,那么就不需要进行早期初始化了。

官方示例直通车

如下我们使用 一对多 的关系来沟通两个模型:

from tortoise import fields
from tortoise.models import Model

class Tournament(Model):
"""
This references a Tournament
"""

    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=100)
    #: The date-time the Tournament record was created at
    created_at = fields.DatetimeField(auto_now_add=True)

class Event(Model):
"""
This references an Event in a Tournament
"""

    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=100)
    created_at = fields.DatetimeField(auto_now_add=True)

    tournament = fields.ForeignKeyField(
        "models.Tournament", related_name="events", description="The Tournament this happens in"
    )

接下来我们使用 pydantic_model_creator 函数来创建 Pydantic 模型:

from tortoise.contrib.pydantic import pydantic_model_creator

Tournament_Pydantic = pydantic_model_creator(Tournament)

如下代码是 Tournament_Pydantic 模型的 JSON-Schema :

>>> print(Tournament_Pydantic.schema())
{
    'title': 'Tournament',
    'description': 'This references a Tournament',
    'type': 'object',
    'properties': {
        'id': {
            'title': 'Id',
            'type': 'integer'
        },
        'name': {
            'title': 'Name',
            'type': 'string'
        },
        'created_at': {
            'title': 'Created At',
            'description': 'The date-time the Tournament record was created at',
            'type': 'string',
            'format': 'date-time'
        }
    }
}

Oh no! 我们 一对多 的关系跑哪儿去了!?

因为模型尚未完全初始化,所以在这个阶段它不知道有 一对多 关系的任何信息。

现在我们需要通过使用 tortoise.Tortoise.init_models() 早期初始化我们的模型关系。

from tortoise import Tortoise

Tortoise.init_models(["__main__"], "models")
# Now lets try again
Tournament_Pydantic = pydantic_model_creator(Tournament)

现在的 Tournament_Pydantic 模型的 JSON-Schema 如下 :

>>> print(Tournament_Pydantic.schema())
{
    'title': 'Tournament',
    'description': 'This references a Tournament',
    'type': 'object',
    'properties': {
        'id': {
            'title': 'Id',
            'type': 'integer'
        },
        'name': {
            'title': 'Name',
            'type': 'string'
        },
        'created_at': {
            'title': 'Created At',
            'description': 'The date-time the Tournament record was created at',
            'type': 'string',
            'format': 'date-time'
        },
        'events': {
            'title': 'Events',
            'description': 'The Tournament this happens in',
            'type': 'array',
            'items': {
                '$ref': '#/definitions/Event'
            }
        }
    },
    'definitions': {
        'Event': {
            'title': 'Event',
            'description': 'This references an Event in a Tournament',
            'type': 'object',
            'properties': {
                'id': {
                    'title': 'Id',
                    'type': 'integer'
                },
                'name': {
                    'title': 'Name',
                    'type': 'string'
                },
                'created_at': {
                    'title': 'Created At',
                    'type': 'string',
                    'format': 'date-time'
                }
            }
        }
    }
}

现在我们可以看到问题迎刃而解了。

请注意,我们也可以以同样的方式为事件(Event)创建一个模型,它同样能正常运行。

Event_Pydantic = pydantic_model_creator(Event)

>>> print(Event_Pydantic.schema())
{
    'title': 'Event',
    'description': 'This references an Event in a Tournament',
    'type': 'object',
    'properties': {
        'id': {
            'title': 'Id',
            'type': 'integer'
        },
        'name': {
            'title': 'Name',
            'type': 'string'
        },
        'created_at': {
            'title': 'Created At',
            'type': 'string',
            'format': 'date-time'
        },
        'tournament': {
            'title': 'Tournament',
            'description': 'The Tournament this happens in',
            'allOf': [
                {
                    '$ref': '#/definitions/Tournament'
                }
            ]
        }
    },
    'definitions': {
        'Tournament': {
            'title': 'Tournament',
            'description': 'This references a Tournament',
            'type': 'object',
            'properties': {
                'id': {
                    'title': 'Id',
                    'type': 'integer'
                },
                'name': {
                    'title': 'Name',
                    'type': 'string'
                },
                'created_at': {
                    'title': 'Created At',
                    'description': 'The date-time the Tournament record was created at',
                    'type': 'string',
                    'format': 'date-time'
                }
            }
        }
    }
}

并且此处 一对多 关系也被定义了!

这两个模型的 schema 中都没有反向关系。这是默认的情况,而在稍后的教程中,我们将展示其相关选项。

让我们来创建并序列化这些对象,看看它们在异步环境中会如何:

# Create objects
tournament = await Tournament.create(name="New Tournament")
event = await Event.create(name="The Event", tournament=tournament)

# Serialise Tournament
tourpy = await Tournament_Pydantic.from_tortoise_orm(tournament)

>>> print(tourpy.model_dump_json())
{
    "id": 1,
    "name": "New Tournament",
    "created_at": "2020-03-02T07:23:27.731656",
    "events": [
        {
            "id": 1,
            "name": "The Event",
            "created_at": "2020-03-02T07:23:27.732492"
        }
    ]
}

在异步环境中对事件进行序列化:

eventpy = await Event_Pydantic.from_tortoise_orm(event)

>>> print(eventpy.model_dump_json())
{
    "id": 1,
    "name": "The Event",
    "created_at": "2020-03-02T07:23:27.732492",
    "tournament": {
        "id": 1,
        "name": "New Tournament",
        "created_at": "2020-03-02T07:23:27.731656"
    }
}

4: PydanticMeta 和可调用对象
这里我们将介绍:

  • 通过 PydanticMeta 类配置模型创建器
  • 使用可调用函数注解额外数据

官方示例直通车

让我们添加一些计算数据的方法,并告诉创建器(creator)如何使用它们:

class Tournament(Model):
    """
    This references a Tournament
    """

    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=100)
    created_at = fields.DatetimeField(auto_now_add=True)

    # It is useful to define the reverse relations manually so that type checking
    #  and auto completion work
    events: fields.ReverseRelation["Event"]

    def name_length(self) -> int:
        """
        Computed length of name
        """
        return len(self.name)

    def events_num(self) -> int:
        """
        Computed team size
        """
        try:
            return len(self.events)
        except NoValuesFetched:
            return -1

    class PydanticMeta:
        # Let's exclude the created timestamp
        exclude = ("created_at",)
        # Let's include two callables as computed columns
        computed = ("name_length", "events_num")


class Event(Model):
    """
    This references an Event in a Tournament
    """

    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=100)
    created_at = fields.DatetimeField(auto_now_add=True)

    tournament = fields.ForeignKeyField(
        "models.Tournament", related_name="events", description="The Tournament this happens in"
    )

    class Meta:
        ordering = ["name"]

    class PydanticMeta:
        exclude = ("created_at",)

这里涉及了很多内容需要解释。

首先,我们定义了一个 PydanticMeta 区块,其中包含了用于创建 Pydantic 模型的可选配置选项。可查看 tortoise.contrib.pydantic.creator.PydanticMeta 获取更多的可用选项信息。

其次,我们在两个模型中都排除了 created_at 字段,因为我们认为它没有任何必要。

第三,我们添加了两个可调用函数:name_lengthevents_num。我们希望这些函数作为结果集的一部分。需要注意的是,可调用函数/计算字段需要手动指定返回类型,因为如果没有指定,我们无法确定记录返回类型,而这是创建有效 Pydantic schema 所必需的。对于标准的 Tortoise ORM 字段,并不需要这样做,因为这些字段已经定义了有效的返回类型。

值得注意的是,Pydantic 序列化器无法调用异步方法,但由于 Tortoise 辅助函数预取了关联的数据,因此在序列化之前可以使用这些数据。因此,我们不需要等待关联的数据返回。但是,我们还是需要防范没有预取数据的情况,因此需要捕获并处理 tortoise.exceptions.NoValuesFetched 异常。

现在我们使用 pydantic_model_creator 方法创建我们的 Pydantic 模型:

from tortoise import Tortoise

Tortoise.init_models(["__main__"], "models")
Tournament_Pydantic = pydantic_model_creator(Tournament)

如下代码是 Tournament_Pydantic 模型的 JSON-Schema :

{
    "title": "Tournament",
    "description": "This references a Tournament",
    "type": "object",
    "properties": {
        "id": {
            "title": "Id",
            "type": "integer"
        },
        "name": {
            "title": "Name",
            "type": "string"
        },
        "events": {
            "title": "Events",
            "description": "The Tournament this happens in",
            "type": "array",
            "items": {
                "$ref": "#/definitions/Event"
            }
        },
        "name_length": {
            "title": "Name Length",
            "description": "Computes length of name",
            "type": "integer"
        },
        "events_num": {
            "title": "Events Num",
            "description": "Computes team size.",
            "type": "integer"
        }
    },
    "definitions": {
        "Event": {
            "title": "Event",
            "description": "This references an Event in a Tournament",
            "type": "object",
            "properties": {
                "id": {
                    "title": "Id",
                    "type": "integer"
                },
                "name": {
                    "title": "Name",
                    "type": "string"
                }
            }
        }
    }
}

注意,created_at 字段被移除,并且添加了name_lengthevents_num 字段。

让我们在异步环境中创建并序列化对象,看看将会如何:

# Create objects
tournament = await Tournament.create(name="New Tournament")
await Event.create(name="Event 1", tournament=tournament)
await Event.create(name="Event 2", tournament=tournament)

# Serialise Tournament
tourpy = await Tournament_Pydantic.from_tortoise_orm(tournament)

>>> print(tourpy.model_dump_json())
{
    "id": 1,
    "name": "New Tournament",
    "events": [
        {
            "id": 1,
            "name": "Event 1"
        },
        {
            "id": 2,
            "name": "Event 2"
        }
    ],
    "name_length": 14,
    "events_num": 2
}

创建器(Creators)

tortoise.contrib.pydantic.creator.pydantic_model_creator

tortoise.contrib.pydantic.creator.pydantic_model_creator(
    cls,
    *,
    name=None,
    exclude=(),
    include=(),
    computed=(),
    optional=(),
    allow_cycles=None,
    sort_alphabetically=None,
    _stack=(),
    exclude_readonly=False,
    meta_override=None,
    model_config=None,
    validators=None,
    module='tortoise.contrib.pydantic.creator'
)

[官方示例直通车]

该函数基于 Tortoise 模型,用于创建 Pydantic 模型。


参数

属性名描述默认值
_stack用于跟踪递归的内部参数()
clsTortoise 源模型类-
name显式指定自定义名称,而不是使用一个自动生成的名称。None
exclude从指定的模型中排除额外的字段。()
include从指定的模型中获取额外的字段。()
computed从指定的模型中获取额外的计算字段。()
optional为指定的模型添加额外的可选字段。()
allow_cycles在生成模型时,允许存在的循环引用控制选项。这对于涉及递归或自引用模型非常有用。None (默认 False)
sort_alphabetically按照字母顺序对参数进行排序,而不是按照字段定义的顺序进行。排序时会按照字段定义的顺序、发现的反向关系的顺序、提供的计算函数的顺序进行。None (默认 False)
exclude_readonly构建一个子模型,其中不包含任何只读字段。False
meta_override用于重写模型的数值的 PydanticMeta 类。None
model_config一个用作 Pydantic 配置的自定义配置。None
validators一个验证字段的方法字典。None
module模型所属的模块名称。注意:创建 Pydantic 模型时使用 config_class 参数,并将 PydanticMetaconfig_class 作为其 Config 类的基类(仅在有提供此参数时)!但它忽略了 字段(config) 配置。此时 pydantic_model_creator 将通过 include/exclude/computed 参数自动生成字段。'tortoise.contrib.pydantic.creator'
返回类型Type[PydanticModel]-

tortoise.contrib.pydantic.creator.pydantic_queryset_creator()

tortoise.contrib.pydantic.creator.pydantic_queryset_creator(
    cls,
    *,
    name=None,
    exclude=(),
    include=(),
    computed=(),
    allow_cycles=None,
    sort_alphabetically=None
)

[官方示例直通车]

该函数基于 Tortoise 模型,用于创建 Pydantic 模型列表。

属性名描述默认值
cls将 Tortoise 源模型类放入一个列表中。-
name显式指定自定义名称,而不是使用一个自动生成的名称。当前生成的列表名称很简单,只是在单数名词的末尾添加了一个“s”。None
exclude从指定的模型中排除额外的字段。()
include从指定的模型中获取额外的字段。()
computed从指定的模型中获取额外的计算字段。()
allow_cycles在生成模型时,允许存在的循环引用控制选项。这对于涉及递归或自引用模型非常有用。默认情况下,该选项取值为 False(即默认不允许循环引用),这将阻止所有形式的回溯。None (默认 False)
sort_alphabetically按照字母顺序对参数进行排序,而不是按照字段定义的顺序进行。排序时会按照字段定义的顺序、发现的反向关系的顺序、提供的计算函数的顺序进行。None (默认 False)
返回类型Type[PydanticListModel]-

PydanticMeta

tortoise.contrib.pydantic.creator.PydanticMeta
class tortoise.contrib.pydantic.creator.PydanticMeta

官方源代码直通车

PydanticMeta 类用于配置生成 Pydantic 模型的元数据。

用法:

class Foo(Model):
    ...

    class PydanticMeta:
        exclude = ("foo", "baa")
        computed = ("count_peanuts", )
属性名类型默认值描述
allow_cyclesboolFalse允许递归中存在循环 - 这可能导致数据量极大 - 请谨慎使用!请结合 exclude/include 功能和适当的 max_recursion 使用
backward_relationsboolTrue使用没有注释的反向关系 - 不建议,可能会导致数据量巨大且无法控制。
computedtuple[str, ...]()在这里可以列出计算字段,以在 Pydantic 模型中使用。
excludetuple[str, ...]('Meta',)在该属性中列出的字段将被从 Pydantic 模型中排除。
exclude_raw_fieldsboolTrue排除关系字段中带有 _id 后缀的原始字段。
includetuple[str, ...]()如果此属性不为空,那么生成的 Pydantic 模型将仅包含指定的字段,而不是模型中所有的字段。
max_recursionint3递归深度的最大允许值。
model_configConfigDictNoneNone
sort_alphabeticallyboolFalse对字段按字母顺序排序;如果未设置(或设置为 False),则保持字段声明顺序不变。

Model Classes

tortoise.contrib.pydantic.base.PydanticListModel
class tortoise.contrib.pydantic.base.PydanticListModel(root=PydanticUndefined, **data)

[官方示例直通车]

用于 Tortoise Models 列表的 Pydantic BaseModel

这提供了一个额外的方法,超出了常用的 Pydantic 模型属性 (model properties

async classmethod from_queryset(queryset)

官方源代码直通车

返回一个可序列化的 Pydantic 模型实例,其中包含来自提供的查询集的模型列表。

这个操作将自动获取并加载所有相关的数据关联。

参数描述
queryset : QuerySet在 PydanticListModel 所对应的数据模型上的一个查询集
返回类型typing_extensions.Self
model_computed_fields : ClassVar[dict[str, ComputedFieldInfo]] = {}

计算字段名称及其对应的 ComputedFieldInfo 对象的字典。

model_config : ClassVar[ConfigDict] = {}

模型的配置应该是符合 [ConfigDict][pydantic.config.ConfigDict] 规范的字典。

model_fields : ClassVar[dict[str, FieldInfo]] = {'root': FieldInfo(annotation=~RootModelRootType, required=True)}

(定义在模型上的)字段的元数据会将字段名映射到 [FieldInfo][pydantic.fields.FieldInfo]

这个方法取代了 Pydantic V1 中的 Model.__fields__方法。

class tortoise.contrib.pydantic.base.PydanticModel(**data)

[官方源代码直通车]

Pydantic BaseModel 用于 Tortoise 对象。

这提供了比常用的 Pydantic 模型属性(model properties)更多的方法。

async classmethod from_queryset(queryset)

[queryset] -[官方源代码直通车]

返回一个可序列化的 Pydantic 模型实例,其中包含来自提供的查询集的模型列表。

这个操作将自动获取并加载所有相关的数据关联。

参数描述
queryset : QuerySet在 PydanticModel 所对应的数据模型上的一个查询集
返回类型List[typing_extensions.Self]
async classmethod from_queryset(queryset)

[queryset] -[官方源代码直通车]

从给定的一组查询结果中返回一个用于单个数据模型的可序列化 Pydantic 模型实例。

这个操作将自动获取并加载所有相关的数据关联。

参数描述
queryset : QuerySetSingle在 PydanticModel 所对应的数据模型上的一个查询集
返回类型typing_extensions.Self
async classmethod from_tortoise_orm(obj)

[obj] -[官方源代码直通车]

从提供的模型实例构建一个可序列化的 Pydantic 模型实例并返回。

当你执行查询时,系统会自动获取所有相关数据。这很可能就是你想要实现的功能。
如果你不希望自动获取数据,或者需要同步(aync)方法,请考虑使用 .from_orm() 方法。
在这种情况下,你需要自己管理预取操作,或者通过使用 tortoise.contrib.pydantic.creator.PydanticMeta 排除关联字段,否则会出现 OperationalError 异常。
这是由于 asyncio 框架强制 I/O 操作在明确的 await 语句中进行。因此,我们只能在等待的方法中进行延迟获取操作。

参数描述
obj你想要序列化的模型实例
返回类型typing_extensions.Self
model_computed_fields : ClassVar[dict[str, ComputedFieldInfo]] = {}

一个包含计算字段名称及其对应的 ComputedFieldInfo 对象的字典。

model_config : ClassVar[ConfigDict] = {'from_attributes': True}

模型的配置应该是符合 [ConfigDict][pydantic.config.ConfigDict] 规范的字典。

model_fields : ClassVar[dict[str, FieldInfo]] = {}

(定义在模型上的)字段的元数据会将字段名映射到 [FieldInfo][pydantic.fields.FieldInfo]

这个方法取代了 Pydantic V1 中的 Model.__fields__方法。