Graphene-django 与 ManyToMany &直通表 [英] Graphene-django with ManyToMany & through-table

查看:17
本文介绍了Graphene-django 与 ManyToMany &直通表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My app has several many-to-many relationships with a through-model like so:

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):

It would seem intuitive to represent this data in graphql without an intermediate type for Membership (option 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 的任何示例.如何做到这一点,是否支持开箱即用?

I could not find any examples on how to implement option A with (django-)graphene. How could it be done and is this supported to work out of the box?

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

What are the pros and cons on both approaches? The data needs to be also mutated quite often, does it alter the verdict?

推荐答案

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

You can achieve this by creating a type which expresses fields from both models. For example:

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(其中 继承自 to express输出中的字段您需要两件事:

For any type built from Graphene's ObjectType (which DjangoObjectType descends from), to express a field in output you need two things:

  1. 字段的类型的声明
  2. 生成要转换为该类型的结果的解析器方法

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

DjangoObjectType evaluates the model you provide it to generate these automatically and uses the fields attribute to let you customize what properties to reveal.

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

By customizing fields and then adding manual props/resolvers for what you want to add you can make the type return anything you want.

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

Note the resolvers don't receive self as the first argument, but instead get a value object. The value object is the return value of your query resolver and is generally an instance of your model or an array of models that matched a filter, etc.

这篇关于Graphene-django 与 ManyToMany &直通表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆