具有多对多和直通表的 Graphene-django

Posted

技术标签:

【中文标题】具有多对多和直通表的 Graphene-django【英文标题】:Graphene-django with ManyToMany & through-table 【发布时间】:2019-09-16 18:03:23 【问题描述】:

我的应用有几个多对多关系与直通模型,如下所示:

class Person(models.Model):
    name = models.CharField()

class Group(models.Model):
    name = models.CharField()
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()  # Extra info on the relationship

如果没有中间类型的 Membership(选项 A),在 graphql 中表示这些数据似乎很直观:


  "data": 
    "persons": [
      
        "id": "1",
        "name": "Jack",
        "groups": [
          
            "id": 3,                     # From Group-model
            "name": "Students",          # From Group-model
            "date_joined": "2019-01-01"  # From Membership-model
          ,
          ...
        ]
      
    ]
  

对比选项 B:


  "data": 
    "persons": [
      
        "id": "1",
        "name": "Jack",
        "memberships": [
          
            "id": 9,
            "date_joined": "2019-01-01"
            "group": 
              "id": 3, 
              "name": "Students"
            
          ,
          ...
        ]
      
    ]
  

我找不到任何关于如何使用 (django-)graphene 实现选项 A 的示例。怎么做?这是否支持开箱即用?

这两种方法的优缺点是什么?数据也需要经常变异,它会改变判断吗?

【问题讨论】:

在此期间你能完成这项工作吗? @R.Wenger 不,我最终编写了一个简单易用的 REST API。 【参考方案1】:

您可以通过创建一个表示两个模型的字段的类型来实现这一点。例如:

import graphene
from graphene_django.types import DjangoObjectType


# hybrid type, expresses some characteristics of Member and Group
class UserGroupType(DjangoObjectType):
    class Meta:
        model = Membership
    
        # date_joined is automatically derived from the membership
        # instance, name and id are declared below.
        fields = ('id', 'name', 'date_joined', )
    
    id = graphene.ID()
    name = graphene.String()
    
    def resolve_id(value_obj, info):
        return value_obj.group.pk

    def resolve_name(value_obj, info):
        return value_obj.group.name


class PersonType(DjangoObjectType):
    class Meta:
        model = Person
    
        # id and name are automatically derived from the person
        # instance, groups is declared below, overriding the 
        # normal model relationship.
        fields = ('id', 'name', 'groups', )
    
    groups = graphene.List(UserGroupType)
    
    def resolve_groups(value_obj, info):
        return value_obj.memberships

对于从 Graphene 的 ObjectType(其中 DjangoObjectType descends from)构建的任何类型,要在输出中表达一个字段,您需要两件事:

    字段type的声明 一种解析器方法,可生成要转换为该类型的结果

DjangoObjectType 评估您提供的模型以自动生成这些模型,并使用fields attribute 让您自定义要显示的属性。

通过自定义fields,然后为您想要添加的内容添加手动道具/解析器,您可以使类型返回您想要的任何内容。

请注意,解析器不会接收self 作为第一个参数,而是接收value object。值对象是查询解析器的返回值,通常是模型的实例或匹配过滤器的模型数组等。

【讨论】:

以上是关于具有多对多和直通表的 Graphene-django的主要内容,如果未能解决你的问题,请参考以下文章

如何保存具有直通关系的多对多字段

Hibernate映射关系:一对一对多和多对多

同一实体之间的一对多和多对多关系

JPA 多对多和 mappedBY

如何判断一对一对多和多对多的关系

多对多和形式 Symfony2