0

category model this my category model

class Category(models.Model):
    _id = models.ObjectIdField(primary_key=True)
    name = models.CharField(max_length=100)

Category node I've created a category node using relay

class CategoryNode(DjangoObjectType):
    class Meta:
        model = Category
        filter_fields = ['name', 'equipments']
        interfaces = (relay.Node,)

add equipmemt mutation while mutation i need to add a category object to equipment object in mutation inputs

class AddEquipment(relay.ClientIDMutation):
    class Input:
        name = graphene.String(required=True)
        category = graphene.Field(CategoryNode)

    equipment = graphene.Field(EquipmentNode)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **inputs):
        equipment_instance = Equipment(
            name=inputs.get('name'),
            category=inputs.get('category')
        )
        equipment_instance.save()
        return AddEquipment(equipment=equipment_instance)

by this code iam getting error like this

"AssertionError: AddEquipmentInput.category field type must be Input Type but got: CategoryNode."

1 Answers1

0

Unfortunately you can't do that as an ObjectType cannot be an InputObjectType. The only way for you to make it work is to create a new class which derived from the InputObjectType.

class CategoryInput(graphene.InputObjectType):
    id = graphene.ID(required=True)
    name = graphene.String()

and use it.

class AddEquipment(relay.ClientIDMutation):
    class Input:
        name = graphene.String(required=True)
        category = graphene.Field(CategoryInput, required=True)

    ...

UPDATE

I think in your case, If you only want to get the category instance there would be no point to input a whole detail of category in your mutation so I suggest to only input the name and the category id in your inner class Input and get query a category instance see example inside your mutate_and_get_payload.

So to be precise you should refactor your code into:

class AddEquipment(relay.ClientIDMutation):
    class Input:
        name = graphene.String(required=True)
        category_id = graphene.ID(required=True)

    equipment = graphene.Field(EquipmentNode)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **inputs):
        # if ID is global make sure to extract the int type id.
        # but in this case we assume that you pass an int.
        category_instance = Category.objects.get(id=inputs.get('category_id'))
        equipment_instance = Equipment(
            name=inputs.get('name'),
            category=category_instance
        )
        equipment_instance.save()
        return AddEquipment(equipment=equipment_instance)
Shift 'n Tab
  • 8,808
  • 12
  • 73
  • 117
  • this is my mutataion mutation{ addEquipment(input:{name:"test equipment",category:{name:"server equipments",id:"5d9a2231e1c4888946342b4d"}}){ equipment{ name } } } – Ram prasanth Oct 22 '19 at 18:49
  • Your error is from here `equipment_instance = Equipment( name=inputs.get('name'), category=inputs.get('category') )` the category only accept category instance rather than an object. – Shift 'n Tab Oct 23 '19 at 09:13
  • yea bro , i cannot find a documentation to pass an instance of an object in graphiql – Ram prasanth Oct 24 '19 at 18:24
  • It would be helpful if you can provide me an example to pass an instance of an object to mutation. TIA @Roel – Ram prasanth Oct 24 '19 at 18:31
  • Bro, thanks for the update, i am unable to resolve the errors. `graphql.error.located_error.GraphQLLocatedError: FAILED SQL: INSERT INTO "equipments_equipment" ("name", "description", "category_id") VALUES (%(0)s, %(1)s, %(2)s) Params: ['test equipment', 'rfbejvbjt', ObjectId('5da8a6deb0023da01550eff1')] Version: 1.2.36` – Ram prasanth Oct 26 '19 at 12:37
  • Like i said in my answer you need to convert the global id which is a string you pass into `category_id ` to int type. I suggest before you dive into this stuff please read the documentation as it is very helpful. – Shift 'n Tab Oct 26 '19 at 16:42