如何在sgqlc的Operation中让Input类型参数直接作为字段传入?
sgqlc:保留Input参数封装的同时扁平化查询参数
问题背景
现有如下示例代码:
from sgqlc.types import * class Input(Input): a = bool b = bool class Nodes(Type): point = float description = str class Query(Type): point = Field(Nodes, args={'vehicle':Input}) query = Operation(Query) query.point(vehicle={'a':False,'b':True}) print(query)
当前输出结果:
query { point(vehicle: {a: false, b: true}) { point description } }
期望得到的输出:
query { point(a: false, b: true) { point description } }
已知直接在Query中定义独立参数可以实现需求:
class Query(Type): point = Field(Nodes, args={'a':bool, 'b': bool})
但需求是必须将所有参数封装在Input类型中,即保持Query的定义为:
class Query(Type): point = Field(Nodes, args={'vehicle':Input})
需要找到实现该需求的方法。
解决方案
可以通过修改sgqlc生成的查询AST(抽象语法树),将嵌套的Input参数展开为字段的直接参数,具体代码如下:
from sgqlc.types import * from sgqlc.operation import Operation class Input(Input): a = bool b = bool class Nodes(Type): point = float description = str class Query(Type): point = Field(Nodes, args={'vehicle':Input}) query = Operation(Query) query.point(vehicle={'a':False,'b':True}) # 遍历查询字段,展开vehicle参数 for field in query.selection_set.fields: if field.name == 'point': # 定位到vehicle参数节点 vehicle_arg = next(arg for arg in field.args if arg.name == 'vehicle') # 将Input对象的子参数转为point字段的直接参数 field.args.extend(vehicle_arg.value.fields) # 删除原有的vehicle参数 field.args.remove(vehicle_arg) print(query)
运行后输出结果:
query { point(a: false, b: true) { point description } }
实现思路
sgqlc构建查询时会生成AST结构,我们直接操作这个结构来调整参数格式:
- 找到目标查询字段
point - 提取
vehicle参数内部的子字段 - 将子字段添加为
point的直接参数 - 移除原有的
vehicle参数
这种方式既满足了用Input类型封装参数的要求,又能生成扁平化的查询参数。
内容的提问来源于stack exchange,提问作者trung
相关产品推荐
相关产品推荐

