如何在 Django-Graphene 中进行多对多突变?

How to make Many-to-many mutations in Django-Graphene?

我正在使用 Django 3.2 和 graphene-django 2.15。 顺便学习一下Graphene的使用方法

注意:我不允许分享所有代码,所以为了这个问题我重写了它。如果您发现任何与问题无关的错误,请通知我。

我有一个团队模型,它与默认的 Django 组模型具有多对多关系:

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
  }
}

我不太明白石墨烯是如何管理多对多关系的。 有人对我有解决方案和一些解释吗?非常感谢。

我找到了解决方案。

一开始以为是跟石墨烯有关的东西,尤其是这几个InputObjectTypes,没看对

其实问题很简单

GroupInput 需要一个单独的值,它是一个 ID。

class GroupInput(graphene.InputObjectType):
    id = graphene.ID(required=True)

因为我把它放在 graphene.List() 中,所以我现在需要一个 ID 列表:

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]
  ) {
    ...
  }

注一:

graphene.ID 也接受以字符串形式给出的 ID:

    groupsId: ["1", "2"]

注2:

我实际上删除了 GroupInput 并将 graphene.ID 字段直接放在 graphene.List:

class UpdateTeam(graphene.Mutation):
    ...

    class Arguments:
        ...
        groups_id = graphene.List(graphene.ID, required=True)