如何在Django-Graphene中正确返回Django ORM Union合并查询结果
问题根因
- 字段类型定义错误:你当前把
get_farm_activities定义为单个FarmActivities对象,但resolver返回的是合并后的列表,类型不匹配导致解析失败。 - 值解析逻辑不匹配:Django ORM的
values()方法返回的是字典格式结果,而Graphene默认的ObjectType字段解析逻辑是读取对象的属性,不是字典的键值,所以无法正确取到id和name的值。 - UUID类型未序列化:ORM返回的id是UUID对象,直接返回的话字符串类型字段无法自动识别转换。
修复方案
第一步:修正查询字段的返回类型
把单个Field改成List类型,匹配返回的列表结构:
class Query(graphene.ObjectType): # 把graphene.Field改为graphene.List get_farm_activities = graphene.List(FarmActivities, farm=graphene.String(required=True)) def resolve_get_farm_activities(self, info, farm): # 后续逻辑参考下方调整
第二步:调整ORM查询逻辑,直接返回模型实例
不需要手动用values()取字段,直接返回模型实例即可,Graphene会自动从实例属性读取对应字段,同时自动处理UUID转字符串的逻辑,用only()方法可以优化查询性能,只拉取需要的字段:
from itertools import chain def resolve_get_farm_activities(self, info, farm): farm_activities = Activity.objects.filter( farmtypeactivityrel__farm_type__farm=farm, deleted_at=None ).only("id", "name") custom_activities = CustomActivity.objects.filter( farm=farm, deleted_at=None ).only("id", "name") return list(chain(farm_activities, custom_activities))
可选兼容方案:如果必须使用values()返回字典
如果业务要求必须用values()返回字典结构,需要给FarmActivities添加字段解析逻辑,手动读取字典键值:
class FarmActivities(graphene.ObjectType): id = graphene.String() name = graphene.String() def resolve_id(self, info): return str(self["id"]) def resolve_name(self, info): return self["name"]
扩展方案:正确实现Union返回多类型独有字段
如果你需要保留Activity和CustomActivity各自的独有字段,之前提到的Union方案可以按如下方式实现:
# 定义Union类型 class FarmActivityUnion(graphene.Union): class Meta: types = (ActivityType, CustomActivityType) # 调整查询返回类型 class Query(graphene.ObjectType): get_farm_activities = graphene.List(FarmActivityUnion, farm=graphene.String(required=True)) def resolve_get_farm_activities(self, info, farm): farm_activities = Activity.objects.filter( farmtypeactivityrel__farm_type__farm=farm, deleted_at=None ) custom_activities = CustomActivity.objects.filter( farm=farm, deleted_at=None ) return list(chain(farm_activities, custom_activities))
查询时使用内联片段即可读取对应类型的独有字段:
query GetFarmActivities($farm: String!) { getFarmActivities(farm: $farm) { __typename ... on ActivityType { id name sortOrder } ... on CustomActivityType { id name farm } } }
内容的提问来源于stack exchange,提问作者OpenDataAlex
相关产品推荐
相关产品推荐

