如何在Django Ninja Schema与TypedDict间转换?避免重复定义字段
Django Ninja Schema与TypedDict的字段复用及相互转换
问题背景
现有代码中需要同时定义TypedDict和Ninja Schema,存在字段重复冗余的问题:
from typing import TypedDict from ninja import Schema class MyDict(TypedDict): a: str class MySchema(Schema): a: str
尝试通过class MySchema(Schema, MyDict): pass的多继承写法无法生成正确的Ninja Schema,同时需要实现两者的相互转换方案。
一、避免字段重复定义的方案
由于TypedDict和Ninja Schema的元类机制不同,直接多继承无法生效,可通过注解注入的方式复用字段:
方式1:直接在Schema类中注入注解
from typing import TypedDict from ninja import Schema class MyDict(TypedDict): a: str b: int class MySchema(Schema): model_config = {"extra": "forbid"} # 可选,限制仅允许定义的字段 # 复用TypedDict的字段注解 locals().update(MyDict.__annotations__)
方式2:封装工具函数批量转换
如果需要频繁转换,可封装工具函数实现TypedDict到Schema的动态生成:
def typed_dict_to_ninja_schema(typed_dict_cls): class DynamicSchema(Schema): model_config = {"extra": "forbid"} # 将TypedDict的字段注解复制到Schema DynamicSchema.__annotations__.update(typed_dict_cls.__annotations__) # 给动态类设置合理名称 DynamicSchema.__name__ = f"{typed_dict_cls.__name__}Schema" return DynamicSchema # 使用示例 MyDict = TypedDict("MyDict", {"a": str, "b": int}) MySchema = typed_dict_to_ninja_schema(MyDict)
二、Schema与TypedDict相互转换方案
1. Ninja Schema 转 TypedDict
提取Schema的字段注解,动态生成对应的TypedDict:
def ninja_schema_to_typed_dict(schema_cls): from typing import TypedDict # 过滤掉Schema内部的私有字段 valid_annotations = { k: v for k, v in schema_cls.__annotations__.items() if not k.startswith('_') } return TypedDict(f"{schema_cls.__name__}TypedDict", valid_annotations) # 使用示例 class MySchema(Schema): a: str b: int MyDict = ninja_schema_to_typed_dict(MySchema)
2. TypedDict 转 Ninja Schema
复用前面的typed_dict_to_ninja_schema工具函数即可。
为什么多继承无效?
TypedDict的元类是TypedDictMeta,而Ninja Schema基于Pydantic,使用的是Pydantic的ModelMetaclass元类,两者的字段解析逻辑完全独立,多继承时无法将TypedDict的字段自动映射到Schema中,因此直接继承不生效。
内容的提问来源于stack exchange,提问作者Vulwsztyn
相关产品推荐
相关产品推荐

