Search code examples
djangographqlgraphene-django

Returning array of deleted objects in single GraphQL mutation (graphene-django)


While in the past I used a GraphQL mutation that deletes a single record, I came up with the idea that this is not ideal in the case I want to delete several records at once since it ended up by calling the mutation that delete 1 record several times (in a loop) which results in several API call over the network.

So I decided to instead modify the mutation to accept has an argument a list of objects or IDs (whatever) on which I can loop in the backend. By doing this, it does only 1 call to the API with all the records to delete.

I managed to do it and the only blocking point that I face is the return statement. I couldn't figure out how to write it.

So if I have a model (in my schema) such as :

class UserType(DjangoObjectType):
  class Meta:
    model = User
    fields = (
        'id',
        'username',
        'password',
        'first_name',
        'last_name',
        'is_active',
        'group_ids',
    )

  full_name = graphene.String()
  full_identification = graphene.String()

In the past I used :

class DeleteUser(graphene.Mutation):
  username = graphene.String()

  class Arguments:
    id = graphene.ID()

  def mutate(self, info, **kwargs):
    user = get_object_or_404(User, id=kwargs['id'])
    user.delete()
    return user

class Mutation(graphene.ObjectType):
  delete_user = DeleteUser.Field()

But now I want to do something such as :

class DeleteUsers(graphene.Mutation):
  users = graphene.List(UserType)
  username = graphene.String()

  class Arguments:
    ids = graphene.List(graphene.ID)

  def mutate(self, info, **kwargs):
    deleted_users = []
    for user in User.objects.filter(id__in=kwargs['ids']):
        user.delete()
        deleted_users.append(user)
    return deleted_users

class Mutation(graphene.ObjectType):
  delete_users = DeleteUsers.Field()

You can see in the mutate(..) method of DeleteUsers class that I try to return the deleted_users to be able to do something like : "Users X, Y and Z have been deleted" in the frontend. But I haven't been able to retrieve the data of the users. How can I achieve it ? Maybe I'm missing something.

Currently the GraphQL query I tried for that is :

mutation {
    deleteUsers(
        ids: [5,6,7],
    ) {
        users {
            username
    }
  }
}

but it doesn't work, saying users is null... Don't know how I could retrieve the users in the query.

Thanks in advance.


Solution

  • Well I finally figured out what was the problem (seems talking about a problem solves it, next time I'll try with a plastic duck).

    While the deleted_users was a correct list with the Users, the ouput type of my mutation wasn't set.

    So the solution is to add :

    class Meta:
      output = graphene.List(UserType)
    

    in my mutation

    which results in :

    class DeleteUsers(graphene.Mutation):
    
      class Arguments:
        ids = graphene.List(graphene.ID)
    
      class Meta:
        output = graphene.List(UserType)
    
      def mutate(self, info, **kwargs):
        deleted_users = []
        for user in User.objects.filter(id__in=kwargs['ids']):
            user.delete()
            deleted_users.append(user)
        return deleted_users
    

    Which can be called with the following :

    mutation {
        deleteUsers(
            ids: [5,6,7],
        ) {
        username
        firstName
        # ...
        # And other fields ...
        # ...
      }
    }