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?
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¶
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.
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.
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.
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(...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With