Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Graphene, Passing JSON or dict data as input for Mutation

I have the following situation: I have a User, each user has a Inventory. I'm struggling to declare the user's inventory in the Mutation "CreateUser". Here is the following mutation for creating the user:

mutation Create{
  addUser(UserData:{name:"Shibunika",age:21}
}

I'm trying to declare the user's inventory in this mutation, I expected something like

mutation Create{
  addUser(UserData:{name:"Shibunika",age:21,inventory:{'item1':45,'item2':25}
}s

these number are the quantity of each item. How do I define these inputs in graphene? Would you gently show me a schema for this?

like image 288
Icaro Amorim Avatar asked Jul 07 '18 15:07

Icaro Amorim


People also ask

What is graphene-Django?

Graphene-Django makes it easy to perform mutations. With Graphene-Django we can take advantage of pre-existing Django features to quickly build CRUD functionality, while still using the core graphene mutationfeatures to add custom mutations to a Django project. Simple example¶

How to add pagination to Django graphene requests?

On Django’s Graphene it’s pretty easy to add pagination to our requests. By default, Graphene uses a Relay module to handle the pagination, but we won’t be using that because it is simpler to integrate pagination within our current query’s resolve function. All we have to do is make a few tweaks.

What is graphene in Django?

Graphene is a powerful library that provides an extendable API, making it easier to integrate your current codebase. You could use graphene-python with your stack right out of the box. But today we will be working with its Django integration, which will give us some additional abstractions to work with.

How do I convert a field to an input in Django?

Graphene-Django comes with mutation classes that will convert the fields on Django forms into inputs on a mutation. MyMutation will automatically receive an input argument. This argument should be a dict where the key is name and the value is a string. DjangoModelFormMutation will pull the fields from a ModelForm.


2 Answers

You can create a custom object type to represent a key value pair, and then have a list of these in your user schema.

class InventoryKeyValueType(graphene.InputObjectType):
    name = graphene.String(required=True)
    int_value = graphene.Int(required=True)

class AddUser(graphene.Mutation):
    user = graphene.Field(lambda: UserType)
    ok = graphene.Boolean()

    class Arguments:
        # User Fields
        name = graphene.String()
        ....

        inventory = graphene.List(InventoryKeyValueType)

The syntax is a bit clunky but workable:

mutation { addUser(name:"Shibunika", age:21, inventory:[ {name: "item1", intValue: 45}, {name: "item2", intValue:25}]){ok}

Other Input Types

This approach could easily be extended for other input types beyond integers, for example replacing

    int_value = graphene.Int(...

with

    str_value = graphene.String(...
like image 175
Mark Chackerian Avatar answered Nov 25 '22 07:11

Mark Chackerian


Graphene provides a GenericScalar type. You can use it to input/output generic types like int, str, dict, list, etc.

from graphene import InputObjectType, Mutation, String, Int
from graphene.types.generic import GenericScalar

class UserInput(InputObjectType):
    name = String()
    age = Int()
    inventory = GenericScalar()

class addUser(Mutation):
    class Arguments:
        user_data = UserInput()

    def mutate(root, info, user_data):
        # do something with user_data

Your input would look like

mutation Create {
  addUser (
    userData: {
      name: "Shibunika"
      age: 21
      inventory: {
        item1: 45,
        item2: 25
      }
    }
  )
}

Note that inventory can accept any generic input, so make sure to validate it.

Also, when using a GenericScalar field for output (query), you won't be able to query its subfields e.g. item1, item2. But you can write a resolver for that field to make sure only specific subfields are returned.

Here is the link to the corresponding GitHub issue.

In your case, inventory field has a well-defined structure, so Mark Chackerian's solution fits better.

like image 33
mrpandey Avatar answered Nov 25 '22 06:11

mrpandey