`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__'