Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I define custom output types for mutations with graphene-django?

Create/remove/update/delete (CRUD) mutations usually return the corresponding database model instance as output type of the mutation. However for non-CRUD mutations I'd like to define business logic specific mutation output types. E.g. returning the count of list elements + a list of IDs which cannot be mapped 1-to-1 between graphql type and db models. How can I achieve this with graphene-django?

like image 557
thinwybk Avatar asked Feb 04 '20 07:02

thinwybk


1 Answers

List not related to Models

As you want to return both a count and a list of elements, you can create a custom type:

class ListWithCountType(graphene.Scalar):

    @staticmethod
    def serialize(some_argument):
        # make computation here
        count = ...
        some_list = ...
        return { "count": count, "list": some_list }

Then on your mutation you use it like this:

class MyMutation(graphene.Mutation):
    list_with_count = graphene.Field(ListWithCountType)

    @classmethod
    def mutate(cls, root, info, **kwargs):
        some_argument = kwargs.pop("some_argument")
        return cls(list_with_count=some_argument)

Add to your schema:

class Query(graphene.ObjectType):
    my_mutation = MyMutation.Field()

Should return something like:

{
  "data": {
    "list_with_count": {
      "count": <COUNT VALUE>,
      "list": <SOME_LIST VALUE>
    }
  }
}

*PS: if this is only an output, ok. But if you want this type to be an argument, you should also implement "parse_literal" and "parse_value", besides the "serialize".

Here is an example with a custom ErrorType used with forms.

List related to Models

From the docs:

# cookbook/ingredients/schema.py

import graphene

from graphene_django.types import DjangoObjectType

from cookbook.ingredients.models import Category


class CategoryType(DjangoObjectType):
    class Meta:
        model = Category

class Query(object):
    all_categories = graphene.List(CategoryType)

    def resolve_all_categories(self, info, **kwargs):
        return Category.objects.all()

On your schema:

import graphene

import cookbook.ingredients.schema


class Query(cookbook.ingredients.schema.Query, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query)

Then you can query like:

query {
  allCategories {
    id
  }
}

Should return something like:

{
  "data": {
    "allCategories": [
      {
        "id": "1",
      },
      {
        "id": "2",
      },
      {
        "id": "3",
      },
      {
        "id": "4",
      }
    ]
  }
}

Here is an example with user model.

like image 78
pedrobern Avatar answered Oct 18 '22 13:10

pedrobern