You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Graphene中基于REST API实现Device与Installation关联查询问题

问题

我正在用Django Graphene构建GraphQL服务器,数据源是一个RESTful API,目前的Schema代码如下:

class DeviceType(graphene.ObjectType):
    id = graphene.ID()
    reference = graphene.String()
    serial = graphene.Float()

class InstallationType(graphene.ObjectType):
    id = graphene.ID()
    company = graphene.Int()
    device = graphene.ID()

class AllDataType(graphene.ObjectType):
    device = graphene.Field(DeviceType)
    installation = graphene.Field(InstallationType)

class Query(graphene.ObjectType):
    installation = graphene.Field(
        InstallationType, device_id=graphene.Int(required=True)
    )
    all = graphene.Field(
        AllDataType, serial=graphene.Float(required=True)
    )

    def resolve_installation(self, info, device_id):
        response = api_call('installations/?device=%s' % device_id)['results'][0]
        return json2obj(json.dumps(response))

    def resolve_all(self, info, serial):
        response = api_call('devices/?serial=%s' % serial)['results'][0]
        return json2obj(json.dumps(response))

我需要执行这样的查询:

query {
    all(serial:201002000856){
        device{
            id
            serial
            reference
        }
        installation{
            company
            device
        }
    }
}

现在遇到的问题是:怎么在AllDataType里建立DeviceType和InstallationType的关联?resolve_installation需要传入设备ID,而resolve_all是通过设备序列号获取Device数据的,我想利用resolve_all返回的Device ID来解析对应的Installation,该怎么实现?

解决方案

其实这事很简单,你只需要给AllDataType添加一个对应的resolve_installation方法就搞定了。在Graphene里,字段的解析函数可以直接定义在它的父类型上,这样就能拿到父对象(也就是AllDataType的实例)里已经获取到的device数据,进而用device ID去调用API拿对应的Installation信息。

具体改法看这里:

  1. 给AllDataType添加解析安装信息的方法:
class AllDataType(graphene.ObjectType):
    device = graphene.Field(DeviceType)
    installation = graphene.Field(InstallationType)

    def resolve_installation(self, info):
        # 这里的self就是resolve_all返回的AllDataType实例,已经包含device的数据了
        device_id = self.device.id
        # 直接复用你之前写好的API调用逻辑就行
        response = api_call('installations/?device=%s' % device_id)['results'][0]
        return json2obj(json.dumps(response))
  1. 确认下你的resolve_all返回的对象里确实包含device的id——从你现在的代码来看,resolve_all是从devices/?serial=xxx接口拿数据,这个接口返回的device对象肯定带id,所以这一步没问题。

这样当你执行目标查询时,Graphene会先跑resolve_all拿到AllDataType的实例,然后解析installation字段的时候,就会调用上面写的resolve_installation方法,用已经拿到的device ID去请求对应的安装信息,完美把device和installation关联起来。

另外还有一种思路:如果以后InstallationType可能在别的场景下也需要通过device ID解析,你也可以把解析逻辑写在InstallationType本身,但这种方式需要传递device ID到上下文或者依赖父对象属性,不如第一种方法直接贴合你当前的需求。比如:

class InstallationType(graphene.ObjectType):
    id = graphene.ID()
    company = graphene.Int()
    device = graphene.ID()

    def resolve_installation(self, info):
        # 这种方式需要提前把device_id放到上下文里,不如第一种直接
        device_id = info.context.get('device_id')
        response = api_call('installations/?device=%s' % device_id)['results'][0]
        return json2obj(json.dumps(response))

但还是第一种方法最适合你现在的场景,逻辑清晰,不需要额外处理上下文,直接用已经拿到的device数据就行。

内容的提问来源于stack exchange,提问作者cardoso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:42:17