如何解决具有多对多关系的石墨烯 django 节点字段

Posted

技术标签:

【中文标题】如何解决具有多对多关系的石墨烯 django 节点字段【英文标题】:How to resolve graphene django node field with Many-to-Many relationship 【发布时间】:2019-03-31 11:44:26 【问题描述】:

当我尝试使用多对多关系解析节点字段时,我收到“收到不兼容的实例错误”。我需要帮助来解决这个问题。我已经列出了graphene django中的模型,graphql类型以供参考。

我使用的代码版本: 石墨烯 django 版本:2.2.0 python 版本:3.5.2 django 版本:(2, 0, 8, 'final', 0)

models.py
---------
class ModelA:
    name
    description

Class ModelB:
    model_code
    description
    field3
    field4
    model_links = models.ManyToManyField(ModelA, through='ModelAModelB')

class ModelAModelB:
    model_a = models.ForeignKey('ModelA', null=True, on_delete=models.CASCADE, db_index=False)
    model_b = models.ForeignKey('ModelB', null=True, on_delete=models.CASCADE, db_index=False)

    class Meta:
        #index is defined here


Graphene Django:


Type Definition
---------------
class ModelANode(DjangoObjectType):
    class Meta:
        model = ModelA
        interfaces = (graphene.relay.Node, )

class ModelBNode(DjangoObjectType):
    modellinks = graphene.Field(ModelANode)

    class Meta:
        model = ModelB
        interfaces = (graphene.relay.Node, )

    def resolve_modellinks(self, info, **args):
        #how do i resolve this field

        #I tried the below code
        modelB = ModelB.objects.get(id=self.id)
        modelaIDs = modelB.modelamodelb_set.select_related('model_a').values_list('model_a_id', flat=True)
        modelARecs = ModelA.objects.filter(id__in=modelaIDs)

        return [graphene.relay.Node.get_node_from_global_id(
                'ModelANode', 
                info,
                to_global_id('ModelANode', rec.id) 
            ) for rec in modelARecs]

Graphql Call:
------------
allmodelBs 
    model_code
    description
    field3
    field4
    modellinks 
        id
    

我获得了模型 B 字段的数据,但模型链接显示以下错误:

"errors": [
    
        "message": "Received incompatible instance \"[None, None]\"."
    ,
    
        "message": "Received incompatible instance \"[]\"."
    
]

我需要帮助来解决多对多关系节点字段。

【问题讨论】:

【参考方案1】:

由于没有使用上下文,我将提及以下内容。

DjangoObjectType 有一个不错的功能 - 您可以使用纯 django 模型实例来代​​替它,并且:

    分辨率结束会转成graphql类型 self 在您的 resolve_* 方法中将是实际的 django 模型

所以你可以使用它:

modelARecs = [rel.model_a for rel in self.modelamodelb_set.all()]

代替:

modelB = ModelB.objects.get(id=self.id)
modelaIDs = modelB.modelamodelb_set.select_related('model_a').values_list('model_a_id', flat=True)
modelARecs = ModelA.objects.filter(id__in=modelaIDs)

然后返回 modelARecs,因为它是 django 模型 DjangoObjectType 声明的。

【讨论】:

上下文是这样的。模型 A 和 B 有一个带有数据透视表 AB 的 MTM rel。模型 B 引用了 A 记录列表,因此我试图获取模型 A 的记录列表以匹配 B 记录。我确实按照您的建议替换了代码,但我仍然收到不兼容的实例错误,显示模型名称和值。 我确实找到了一个解决方案,即不在模型 B 节点中向模型 A 添加引用字段,即在上面的示例中删除模型链接。在查询模型 B 节点时,您将能够使用 model_links 自动获取模型 A 的记录,因为它已在模型 A 中引用。

以上是关于如何解决具有多对多关系的石墨烯 django 节点字段的主要内容,如果未能解决你的问题,请参考以下文章

具有外键关系的对象的石墨烯中的 GraphQL 突变

将 json 模型字段与 django 石墨烯一起使用

从具有多对多关系 django 的两个表中过滤数据

如何在Django Rest Framework中序列化三个具有多对多关系的模型

使用 ajax 轮询缓解繁重的 django 石墨烯请求

有没有办法让石墨烯与 django GenericRelation 字段一起工作?