后端API设计【免费下载链接】grapheneGraphQL framework for Python项目地址https://gitcode.com/gh_mirrors/gr/graphene点击查看免费下载本篇技术指南以 GraphenePython 的 GraphQL 框架官方文档docs/types/enums.rst为主体深入讲解如何在 Graphene 中定义和使用 GraphQLEnum类型从类式与实例式两种定义方式、枚举值描述description、复用既有 PythonEnum的from_enum机制到成员访问、比较、迭代等行为差异并结合仓库源码graphene/types/enum.py、graphene/types/schema.py与测试用例graphene/types/tests/test_enum.py剖析其底层原理。读完本文你将能够熟练地在 Graphene Schema 中设计、定制并安全地使用枚举类型。一、什么是 GraphQL Enum 类型Enum是 GraphQL 中的一种特殊类型它表示一组绑定到唯一、恒定值上的符号名称成员。例如星战示例中的“剧集”只能取NEWHOPE、EMPIRE、JEDI三个值这就是典型的枚举场景。在 GraphQL 中枚举类型出现在 Schema 定义中形如enum Episode { NEWHOPE EMPIRE JEDI }客户端在查询或提交变量时只能使用这些符号名之一Graphene 负责将其与 Python 侧的具体值进行双向映射。官方文档 docs/types/enums.rst 在 Graphene 的 Types Referencedocs/types/index.rst中与schema、scalars、objecttypes、interfaces、unions、mutations并列是构建 Schema 的基础类型之一。二、两种定义方式2.1 使用类class定义最常见的定义方式是直接声明一个继承graphene.Enum的类类属性即枚举成员import graphene class Episode(graphene.Enum): NEWHOPE 4 EMPIRE 5 JEDI 6这里NEWHOPE、EMPIRE、JEDI成为枚举成员分别绑定常量值4、5、6。从源码看graphene/types/enum.py 中的EnumMeta.__new__会收集类字典排除Meta避免与枚举值冲突并以PyEnum(cls.__name__, enum_members)的方式在内部构造一个标准 Python 枚举随后通过__init_subclass_with_meta__enum.py把底层枚举的每个成员setattr到 Graphene 类上因此你可以直接通过Episode.NEWHOPE访问成员。2.2 使用实例instance定义如果不想用类语法也可以直接调用graphene.Enum构造器传入类型名和一个(名称, 值)的二元组列表Episode graphene.Enum(Episode, [(NEWHOPE, 4), (EMPIRE, 5), (JEDI, 6)])这条路径在 enum.py 的EnumMeta.__call__中实现当cls is Enum时它会用PyEnum(*args, **kwargs)构造一个标准 Python 枚举再通过from_enum包装成 Graphene 枚举类型。该构造器还接受description与deprecation_reason关键字参数例如测试用例 test_enum.py 所示RGB Enum(RGB, RED,GREEN,BLUE, descriptionAn enumeration, but with a custom description)两种方式最终生成等价的 Graphene 枚举类型测试 test_enum_instance_construction 验证了实例方式的成员集合与类方式一致。三、为枚举值添加描述Value descriptionsGraphQL 的 Enum 值可以携带描述文本用于生成 Schema 文档自省/introspection。Graphene 要求枚举值具备description属性最直接的做法是在枚举类中定义description属性property按成员区分返回不同的文本class Episode(graphene.Enum): NEWHOPE 4 EMPIRE 5 JEDI 6 property def description(self): if self Episode.NEWHOPE: return New Hope Episode return Other episode注意这里比较用的是self Episode.NEWHOPEGraphene 枚举重写了__eq__enum.py当比较对象是同类成员时按身份比较self is other否则与底层值比较self.value is other因此与普通整数4比较也能成立。当 Schema 被构建时schema.py 的create_enum会遍历底层枚举的__members__读取每个值的description属性组装成GraphQLEnumValue。测试 test_enum_construction 验证了description属性会逐个应用到各成员上。另有一个细节值得注意如果某个枚举成员本身恰好叫description比如小写description descriptioncreate_enum会检测到它是枚举成员isinstance(description, PyEnum)并把它视为成员而非描述参见 schema.py 与测试 test_enum_description_member_not_interpreted_as_property。四、复用既有 Python Enumfrom_enum如果你的代码里已经有定义好的 Python 标准库Enum无需重写直接通过Enum.from_enum复用graphene.Enum.from_enum(AlreadyExistingPyEnum)from_enum的签名enum.py为Enum.from_enum(cls, enum, nameNone, descriptionNone, deprecation_reasonNone)enum待复用的 Python 枚举类必填nameGraphQL 类型名默认取enum.__name__description类型描述默认取enum.__doc__若枚举类没有 docstring 则回退为An enumeration.测试 test_enum_from_python3_enum_uses_default_builtin_doc 验证了该默认值deprecation_reason类型级废弃说明。值得强调的是description和deprecation_reason都支持接收单个枚举值并返回文本的 lambda/函数这样无需改动原始枚举即可为不同成员提供差异化描述或废弃原因graphene.Enum.from_enum( AlreadyExistingPyEnum, descriptionlambda v: foo if v AlreadyExistingPyEnum.Foo else bar )对应的测试用例 test_enum_from_builtin_enum_accepts_lambda_description 展示了完整用法传入按值返回不同描述的custom_description与按值返回废弃原因的custom_deprecation_reason最终在生成的 Schema 中每个枚举值的描述与废弃原因都正确生效。在底层schema.py 的create_enum会逐个成员调用这些可调用对象graphene_type._meta.description(value)/graphene_type._meta.deprecation_reason(value)。五、通过 Meta 配置类型级属性与 Graphene 其他类型一致枚举类也可通过内嵌Meta类配置名称、描述与废弃原因enum.py 的类文档class RGB(graphene.Enum): class Meta: name RGBEnum # 可选GraphQL 类型名默认取类名 description Description # 可选默认取类 docstring # deprecation_reason # 可选标记整个枚举已废弃并给出原因 RED 1 GREEN 2 BLUE 3测试 test_enum_construction_meta 验证了通过 Meta 设置的自定义名称与描述会被记录到_meta中。EnumMeta.__new__会特意把Meta从类字典中剔除enum.py避免Meta被当成枚举成员测试 test_enum_skip_meta_from_members 印证了这一点。deprecation_reason同时支持类型级字符串与成员级可调用对象两种用法。六、成员访问.get与 Python Enum 的差异标准库enum.Enum允许通过“初始化枚举”的方式按值取成员from enum import Enum class Color(Enum): RED 1 GREEN 2 BLUE 3 assert Color(1) Color.RED但 Graphene 的Enum不支持这种直接调用方式需要调用.get达到同样效果from graphene import Enum class Color(Enum): RED 1 GREEN 2 BLUE 3 assert Color.get(1) Color.RED.get在 enum.py 中实现本质上委托给底层枚举cls._meta.enum(value)。除此之外Graphene 枚举还支持按名称取成员Color[RED]由__getitem__实现enum.py测试 test_enum_can_retrieve_members 验证迭代成员for c in TestEnum:可直接遍历因为__iter__委托给底层枚举enum.py测试 test_enum_iteration 验证用作字典键枚举重写了__hash__enum.py因此可以作为 dict/set 的键测试 test_hashable_enum 与 test_hashable_instance_creation_enum 均验证了与普通值如整数1可并存于同一字典。另外注意Graphene 中两个不同的枚举类即使成员同名同值其成员也不相等RGB1.RED ! RGB2.RED见测试 test_enum_to_enum_comparison_should_differ。七、在 Schema 中实际使用 Enum枚举类型可以像标量一样被挂载为字段类型、字段参数或 Mutation 的输入。7.1 作为字段类型class Query(graphene.ObjectType): episode graphene.Field(Episode) def resolve_episode(root, info): return Episode.NEWHOPE # 或返回底层值 4Graphene 的Enum继承自UnmountedTypeenum.py其get_typeenum.py在类型被挂载作为 Field、InputField 或 Argument时返回自身类。挂载后的字段类型即该枚举类测试 test_enum_value_as_unmounted_field 及对应的 InputField、Argument 版本test_enum.py都验证了这一行为。7.2 作为字段参数枚举常用于过滤、分类类参数。在 graphene/types/argument.py 的参数装配逻辑中未挂载的枚举UnmountedType会被自动挂载为Argument因此可以直接写class Query(graphene.ObjectType): bricks_by_color graphene.Field(Brick, colorColor(requiredTrue)) def resolve_bricks_by_color(root, info, color): return Brick(colorcolor)客户端查询{ bricksByColor(color: RED) { color } }时解析器收到的color参数是 Graphene 枚举成员Color.RED测试 test_field_enum_argument 验证了这一点。7.3 作为 Mutation 输入枚举同样可以出现在 Mutation 的Arguments与输入对象类型InputObjectType中class CreatePaint(graphene.Mutation): class Arguments: color RGB(requiredTrue) # 枚举参数 color RGB(requiredTrue) # 枚举输出字段 def mutate(root, info, color): return CreatePaint(colorcolor){ createPaint(color: RED) { color } }执行后返回{createPaint: {color: RED}}且mutate中拿到的color即为RGB.RED把它嵌进InputObjectType同样可用createPaint(colorInput: { color: RED })见测试 test_mutation_enum_input 与 test_mutation_enum_input_type。7.4 解析器返回值兼容成员或原始值均可得益于重写的__eq__与 GraphQL 层的序列化逻辑解析器返回枚举成员或其原始值都可行class Query(graphene.ObjectType): color GColor(requiredTrue) color_by_name GColor(requiredTrue) def resolve_color(_, info): return Color.RED.value # 返回原始值 1 def resolve_color_by_name(_, info): return Color.RED.name # 返回成员名 RED两个字段的查询结果都会是RED测试 test_enum_resolver_compat。但若返回非法值如字符串BLACKGraphQL 执行会报错Enum Color cannot represent value: BLACK见 test_enum_resolver_invalid。八、底层实现解析理解以下两条调用链即可对 Enum 机制了然于胸类型构造定义class Episode(graphene.Enum)时EnumMeta.__new__enum.py把类体剔除Meta转成标准库PyEnum存储为__enum__随后Enum.__init_subclass_with_meta__enum.py将其放入_meta.enum并把成员复制到类上。from_enum则是动态构造一个携带Metaenum/description/deprecation_reason的子类完成包装。Schema 构建Schema.add_type检测到issubclass(graphene_type, Enum)后调用create_enumschema.py后者把每个成员连同其description、deprecation_reason支持可调用对象逐值求值组装成GraphQLEnumValue最终生成 GraphQL 层的GrapheneEnumTypeschema.py。Schema 打印效果可见测试 test_enum_typesPrimary colors enum Color { RED YELLOW BLUE }九、仓库实战Star Wars 示例仓库示例 examples/starwars/schema.py 正是文档中Episode枚举的完整落地class Episode(graphene.Enum): NEWHOPE 4 EMPIRE 5 JEDI 6它在Character接口中作为appears_in列表的元素类型graphene.List(Episode)也在hero字段中作为参数episodeEpisode()。数据层 examples/starwars/data.py 的get_hero直接与整数值比较if episode 5这正是前文所述“枚举可与底层值比较”这一设计带来的便利内存数据按原始值存储Schema 层按符号名交互两者通过枚举无缝衔接。十、小结与注意事项定义方式二选一类式class Episode(graphene.Enum)适合静态声明实例式graphene.Enum(Episode, [...])适合动态生成。枚举值描述通过类内description属性实现类型级描述/废弃信息通过Meta配置复用既有枚举时用from_enum其description/deprecation_reason可传 lambda 逐值定制。访问成员用Color.get(1)按值或Color[RED]按名不要使用 Python 标准库Enum的Color(1)初始化语法。解析器返回值支持枚举成员或原始值但非法值会触发Enum ... cannot represent value错误。枚举可用于字段类型、字段参数、Mutation 参数与输入对象类型其可哈希特性使其可安全用作字典键。如需进一步了解枚举与其他类型的组合用法可继续阅读仓库中的 Scalars、ObjectTypes 与 Mutations 文档。赞分享后端API设计【免费下载链接】grapheneGraphQL framework for Python项目地址https://gitcode.com/gh_mirrors/gr/graphene点击查看免费下载相关推荐transitions状态机与枚举类型使用Enum实现类型安全的状态定义终极指南transitions状态机与枚举类型使用Enum实现类型安全的状态定义终极指南 在Python状态机开发中transitions库提供了强大的类型安全支持后端流程编排想在 PC 上玩 PS3 游戏RPCS3 从开机到调优的 5 件实事想在 PC 上玩 PS3 游戏RPCS3 从开机到调优的 5 件实事 RPCS3 是目前最成熟的开源 PS3模拟器能让你的 PC 直接运行 PS3 游戏——人工智能AI AgentRAG本地部署CLIjsonschema2pojo生成枚举类型完全指南从Schema到Java Enumjsonschema2pojo生成枚举类型完全指南从Schema到Java Enum jsonschema2pojo 是一个强大的Java代码生成工具能够从代码生成开发工具上一篇YimMenu终极指南GTA5游戏体验全面升级方案下一篇手机上的宝可梦存档编辑器PKHeX.Mobile新手完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
