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

标签 django graphql graphene-python

我的应用程序有几个多对多关系 带直通型 像这样:

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

在 graphql 中表示这些数据而没有成员资格的中间类型(选项 A)似乎很直观:
{
  "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 的示例。如何做到这一点,是否支持开箱即用?

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

最佳答案

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

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

适用于由 Graphite 烯制成的任何类型 ObjectType (其中 DjangoObjectType descends from ),要在输出中表达一个字段,您需要做两件事:
  • type的声明领域
  • 生成要转换为该类型的结果的解析器方法
  • DjangoObjectType评估您提供的模型以自动生成这些模型并使用 fields attribute让您自定义要显示的属性。
    通过定制 fields然后为您要添加的内容添加手动 Prop /解析器,您可以使类型返回您想要的任何内容。
    请注意,解析器不会收到 self作为第一个参数,而是得到一个 value object .值对象是查询解析器的返回值,通常是模型的实例或与过滤器匹配的模型数组等。

    关于django - 具有多对多和直通表的 Graphene-django,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55880901/

    相关文章:

    javascript - 从 Graphql 端点返回数据时出错

    django - Graphene Django 查询 Elasticsearch

    python - Graphite 烯在上下文管理器中运行所有解析器

    python - 在 django rest 框架中使用 request.user 进行模型反序列化

    django - 如何在 Django 管理中的 GenericForeignKey 上显示自定义 verbose_name

    django - 如何从 django 1.5 中请求的用户 ID 的 auth_user 表中获取电子邮件地址?

    graphql 基于角色的授权

    node.js - TypeError : obj. hasOwnProperty 在调用 Graphql mutation 时不是一个函数

    python - Graphene 中提供的 GraphQLError() 有多大用处?

    mysql - Django 中的加权搜索