Graphene中如何向嵌套ObjectType传递输入参数?
嵌套类型传递隐藏参数的可行方案
核心实现逻辑
Graphene 构建对外 schema 时,只会识别类作用域下用 Graphene 字段类型(如String()、Int())声明的属性,Python 实例自带的普通属性完全不会被 schema 层感知,也就不存在暴露给前端的问题,完全适配你的需求。
具体实现方式
1. 实例直接挂载隐藏属性(最简洁)
不需要修改类结构,在根 resolver 实例化目标类型时,直接把需要的参数存为实例私有属性,嵌套字段的 resolver 从入参parent(即当前类型的实例)读取即可:
class UserType(ObjectType): firstname = String(required=True) def resolve_firstname(parent, info): # 直接从当前实例读取隐藏的user_id current_user_id = parent._user_id user = get_user_by_id(current_user_id) return user.firstname class Query(ObjectType): user = Field( UserResult, user_id=String(required=True) ) async def resolve_user(parent, info, user_id): try: user_type_instance = UserType() # 这个属性没有用Graphene字段声明,不会暴露到schema user_type_instance._user_id = user_id return user_type_instance except UserNotFoundError: return ErrorType(message="用户不存在")
2. 自定义类型的__init__方法传参
这种方式是完全合规的实现,不存在规范问题,只是把参数传递逻辑封装到类的构造方法中,代码可读性更高:
class UserType(ObjectType): firstname = String(required=True) # 自定义构造方法,*只要不在类作用域声明对应Graphene字段,就不会暴露参数* def __init__(self, user_id: str, *args, **kwargs): super().__init__(*args, **kwargs) self._user_id = user_id def resolve_firstname(parent, info): user = get_user_by_id(parent._user_id) return user.firstname async def resolve_user(parent, info, user_id): return UserType(user_id=user_id)
注意:这种方式和实例直接挂属性的实现本质完全一致,只要不在类内写
user_id = String(required=True)这类字段声明,传入的user_id就永远不会出现在对外的GraphQL schema中。
3. 优化实践:避免嵌套resolver重复查库
实际项目中更推荐的写法是在根resolver阶段一次性完成数据库查询,把查好的业务对象直接挂载到类型实例上,避免每个嵌套字段的resolver都用同一个user_id重复请求数据库:
async def resolve_user(parent, info, user_id): try: # 根resolver一次性查询完成 db_user = get_user_by_id(user_id) user_type_instance = UserType() # 直接挂载完整的业务对象 user_type_instance._db_user = db_user return user_type_instance except UserNotFoundError: return ErrorType(message="用户不存在") class UserType(ObjectType): firstname = String(required=True) lastname = String(required=True) def resolve_firstname(parent, info): # 直接读取已查询好的对象,无需重复查库 return parent._db_user.firstname def resolve_lastname(parent, info): return parent._db_user.lastname
避坑提醒
你之前考虑的“给UserType新增user_id字段传入”的方式会暴露参数,核心原因是如果你在类作用域写了user_id = String(),Graphene会自动把这个字段注册到对外可查询的schema中。只要规避这一点,不管是实例挂属性还是自定义__init__传参,都可以实现“参数内部可用、对外不暴露”的效果。
内容的提问来源于stack exchange,提问作者coryx
相关产品推荐
相关产品推荐

