I'm working in Django 3.2 and graphene-django 2.15. I'm still learning how to use Graphene by the way.
Note: I'm not allowed to share all the code so I rewrote it for the purpose of this question. Please notify me if you've found any error unrelated to the question.
I have an Team model which has a Many-to-Many relationship with the default Django Group model:
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)
Here is my schema:
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)
When I perform this query:
mutation{
updateTeam(
teamId: 65961826547,
name: "My Team Name",
groupsId: [{id: 1}, {id: 2}]
) {
team {
team_id,
name,
groups {
name,
}
}
}
}
I get this error:
{
"errors": [
{
"message": "Field 'id' expected a number but got {'id': '1'}.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateTeam"
]
}
],
"data": {
"updateTeam": null
}
}
I don't really understand how Many-to-may relationships are managed by Graphene. Does someone has a solution and some explanations for me? Thanks a lot.
I found the solution.
At first, I thought there was something related to graphene, especially these InputObjectTypes
, I didn't get correctly.
But the issue is actually very simple.
The GroupInput
is expecting a single value, which it an ID.
class GroupInput(graphene.InputObjectType):
id = graphene.ID(required=True)
Because I put it in graphene.List()
, I'm now expecting a list of ID's:
class UpdateTeam(graphene.Mutation):
...
class Arguments:
...
groups_id = graphene.List(GroupInput, required=True)
But in my API call, instead of giving an actual list, I gave a dict:
mutation{
updateTeam(
...
groupsId: [{id: 1}, {id: 2}]
) {
...
}
So this works:
mutation{
updateTeam(
...
groupsId: [1, 2]
) {
...
}
Note 1:
graphene.ID
also accepts ids given as strings:
groupsId: ["1", "2"]
Note 2:
I actually removed my GroupInput
and put the graphene.ID
field directly in the graphene.List
:
class UpdateTeam(graphene.Mutation):
...
class Arguments:
...
groups_id = graphene.List(graphene.ID, required=True)