Как сделать мутации "многие-ко-многим" в Django-Graphene?
Я работаю в Django 3.2 и graphene-django 2.15. Кстати, я все еще учусь использовать Graphene.
Примечание: Мне не разрешено делиться всем кодом, поэтому я переписал его для целей этого вопроса. Пожалуйста, сообщите мне, если вы нашли какую-либо ошибку, не связанную с вопросом.
У меня есть модель Team, которая имеет отношения "многие-ко-многим" с моделью Django Group по умолчанию:
from django.db import models
from django.contrib.auth.models import Group
class Team(models.Model):
team_id = models.IntegerField(unique=True) # Custom ID not related to Django's pk
name = models.CharField(max_length=255)
groups = models.ManyToManyField(Group, blank=True)
Вот моя схема:
import graphene
from django.contrib.auth.models import Group
from graphene_django import DjangoObjectType
from .models import Team
class TeamType(DjangoObjectType):
class Meta:
model = Team
class GroupType(DjangoObjectType):
class Meta:
model = Group
class GroupInput(graphene.InputObjectType):
id = graphene.ID(required=True)
class UpdateTeam(graphene.Mutation):
team = graphene.Field(TeamType)
class Arguments:
team_id = graphene.ID(required=True)
name = graphene.String(required=True)
groups_id = graphene.List(GroupInput, required=True)
def mutate(self, info, team_id, name, groups_id):
team = Team.objects.get(pk=team_id)
team.name = name
team.groups = Group.objects.filter(pk__in=groups_id)
team.save()
return UpdateTeam(team=team)
class TeamMutations(graphene.ObjectType):
update_team = UpdateTeam.Field()
class Mutation(TeamMutations, graphene.ObjectType):
pass
schema = graphene.schema(query=Query, mutation=Mutation)
Когда я выполняю этот запрос:
mutation{
updateTeam(
teamId: 65961826547,
name: "My Team Name",
groupsId: [{id: 1}, {id: 2}]
) {
team {
team_id,
name,
groups {
name,
}
}
}
}
Я получаю эту ошибку:
{
"errors": [
{
"message": "Field 'id' expected a number but got {'id': '1'}.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateTeam"
]
}
],
"data": {
"updateTeam": null
}
}
Я не очень понимаю, как отношения "многие к многим" управляются в Graphene. Есть ли у кого-нибудь решение или объяснения для меня? Большое спасибо.
Я нашел решение.
Сначала я подумал, что есть что-то связанное с графеном, особенно эти InputObjectTypes, я не понял правильно.
Но на самом деле проблема очень проста.
GroupInput ожидает одно значение, которым является ID.
class GroupInput(graphene.InputObjectType):
id = graphene.ID(required=True)
Поскольку я поместил его в graphene.List(), теперь я ожидаю список идентификаторов:
class UpdateTeam(graphene.Mutation):
...
class Arguments:
...
groups_id = graphene.List(GroupInput, required=True)
Но в моем вызове API, вместо того, чтобы дать фактический список, я дал дикту:
mutation{
updateTeam(
...
groupsId: [{id: 1}, {id: 2}]
) {
...
}
Так это работает:
mutation{
updateTeam(
...
groupsId: [1, 2]
) {
...
}
Примечание 1:
graphene.ID также принимает идентификаторы, заданные в виде строк:
groupsId: ["1", "2"]
Примечание 2:
Я действительно удалил GroupInput и поместил поле graphene.ID непосредственно в graphene.List:
class UpdateTeam(graphene.Mutation):
...
class Arguments:
...
groups_id = graphene.List(graphene.ID, required=True)