`graphene-django`: Определение типа объекта, когда несколько типов объектов GraphQL используют одну и ту же модель django в запросе узла

Это специально для graphene-django при выполнении node(id: ...) {} запроса.

В других вопросах обсуждался graphene, однако graphene-django выполняет определение типов для graphene. Это повторное использование кода из Django-graphene multiple types for the same model, но спрашивается не о доступе к полям, а о поведении типа объекта, использующего одну и ту же модель, отличающегося от идентификатора реле. Может быть, здесь что-то упущено?

Кроме того, в комментариях обсуждается работа над проблемой структурно - например, разделение между публичной и частной схемами API - это не тот случай, это намеренно одна и та же модель на одной схеме с разными полями.

import graphene_django
from .models import Org as OrgModel

class Org(graphene_django.DjangoObjectType):
    class Meta:
        model = OrgModel
        fields = (
            "id",
            "name",
            "billing"
        )

class AnonymousOrg(graphene_django.DjangoObjectType):
    class Meta:
        model = OrgModel
        fields = (
            "id",
            "name",
        )

Предположим запрос к Org с идентификатором 7eca71ed-ff04-4473-9fd1-0a587705f885.

btoa('Org:7eca71ed-ff04-4473-9fd1-0a587705f885')
'T3JnOjdlY2E3MWVkLWZmMDQtNDQ3My05ZmQxLTBhNTg3NzA1Zjg4NQ=='
{
  node(id: "T3JnOjdlY2E3MWVkLWZmMDQtNDQ3My05ZmQxLTBhNTg3NzA1Zjg4NQ==") {
    id
    __typename
    ... on Org {
      id
    }
  }
}

Возврат:

{
  "data": {
    "node": {
      "id": "QW5vbnltb3VzT3JnOjdlY2E3MWVkLWZmMDQtNDQ3My05ZmQxLTBhNTg3NzA1Zjg4NQ==",
      "__typename": "AnonymousOrg"
    }
  }
}

Возвращается объект другого типа 'AnonymousOrg:7eca71ed-ff04-4473-9fd1-0a587705f885', несмотря на то, что идентификатор реле указывает, что это объект Org.

Есть ли в graphene-django способ "подсказки" или детализации, чтобы убедиться, что возвращаемый тип соответствует тому, что указано в ID и его фрагменте?

Заслуга в этом принадлежит @Boolangery (GitHub) workaround 25 мая 2020 года.

class FixRelayNodeResolutionMixin:
    @classmethod
    def get_node(cls, info, pk):
        instance = super(FixRelayNodeResolutionMixin, cls).get_node( info, pk)
        setattr(instance, "graphql_type", cls.__name__)
        return instance

    @classmethod
    def is_type_of(cls, root, info):
        if hasattr(root, "graphql_type"):
            return getattr(root, "graphql_type") == cls.__name__
        return super(FixRelayNodeResolutionMixin, cls).is_type_of(root, info)

Usage, вот пример с моделью django User с двумя объектами Django Graphene, указывающими на нее: PublicUserType и UserType:

from graphene_django import DjangoObjectType


class PublicUserType(FixRelayNodeResolutionMixin, DjangoObjectType):
    class Meta:
        model = User
        interfaces = (graphene.relay.Node,)
        fields = ['id', 'first_name', 'last_name']

class UserType(FixRelayNodeResolutionMixin, DjangoObjectType):
    class Meta:
        model = User
        interfaces = (graphene.relay.Node,)
        fields = ['id', 'first_name', 'last_name', 'profile']

Сегодня у меня была такая же проблема и я решил ее как stackoverflow

Для меня работает изменение порядка типов классов от типа класса с меньшим количеством полей к типу класса с большим количеством полей.

Так,

class AnonymousOrg(graphene_django.DjangoObjectType):
    class Meta:
        model = OrgModel
        fields = (
            "id",
            "name",
        )

class LiteOrg(graphene_django.DjangoObjectType):
    class Meta:
        model = OrgModel
        fields = (
            "id",
            "name",
            "billing"
        )

class OrgAll(graphene_django.DjangoObjectType):
        class Meta:
            model = OrgModel
            fields = '__all__'
Вернуться на верх