Search code examples
pythonpython-3.xgraphqlgraphene-django

GraphQL returns null for update and delete mutation


I am using graphene-django library for integrating GraphQL Schema into my Django application.

I have implemented Queries; get all and get specific, as well as implemented create, update and delete Mutations. All endpoints are working as expected except for the update and delete.

Here is what my model looks like:

COUNTRIES = (
    ("sierra leone",  "Sierra Leone"),
    ("guinea", "Guinea"),
)

class School(models.Model):
    name = models.CharField(_("Name"), max_length=255)
    abreviation = models.CharField(_("Abreviation"), max_length=10)
    label = models.TextField(_("Label"), max_length=255, blank=True, null=True)
    school_id = models.CharField(_("School ID"), max_length=100, unique=True, blank=True, null=True)
    adresse_line_1 = models.CharField(_("Adresse Line 1"), max_length=255, blank=True)
    adresse_line_2 = models.CharField(_("Adresse Line 2"), max_length=255, blank=True)
    city = models.CharField(_("City"), max_length=255, blank=True)
    country = models.CharField(max_length=60, choices=COUNTRIES, blank=True, null=True)
    phone_number = models.CharField(_("Phone number"), max_length=15)
    email = models.EmailField(_("Email"))
    website = models.CharField(_("Website"), max_length=50, blank=True)
    logo = models.ImageField(_("Logo"), upload_to='logo/', blank=True)
    small_logo = models.ImageField(_("Small Logo"), upload_to='logo/', blank=True, null=True)
    site_favicon = models.ImageField(_("Favicon"), upload_to='logo/', blank=True, null=True)

And here is the code for my update and delete mutations:

class SchoolType(DjangoObjectType):
    class Meta:
        model = School
        fields = (
            "name",
            "abreviation",
            "label",
            "school_id",
            "adresse_line_1",
            "adresse_line_2",
            "city",
            "country",
            "phone_number",
            "email",
            "website",
            "logo",
            "small_logo",
            "site_favicon",
        )
        interfaces = (graphene.relay.Node,)
        convert_choices_to_enum = False

class UpdateSchoolMutation(graphene.Mutation):
    school = graphene.Field(SchoolType)
    success = graphene.Boolean()

    class Arguments:
        id = graphene.String(required=True)
        name = graphene.String()
        abreviation = graphene.String()
        label = graphene.String()
        school_id = graphene.String()
        adresse_line_1 = graphene.String()
        adresse_line_2 = graphene.String()
        city = graphene.String()
        country = graphene.String()
        phone_number = graphene.String()
        email = graphene.String()
        website = graphene.String()
        logo = Upload()
        small_logo = Upload()
        site_favicon = Upload()

    @classmethod
    def mutate(self, info, id, **kwargs):
        id = int(from_global_id(id)[1])

        try:
            school = School.objects.get(pk=id)
        except School.DoesNotExist:
            raise Exception("School does not exist".format(id))

        for field, value in kwargs.items():
            setattr(school, field, value)

        school.save()
        return UpdateSchoolMutation(school=school, success=True)


class DeleteSchoolMutation(graphene.Mutation):
    success = graphene.Boolean()

    class Arguments:
        id = graphene.String(required=True)

    @classmethod
    def mutate(self, info, id, **kwargs):
        id = int(from_global_id(id)[1])
        
        try:
            school = School.objects.get(pk=id)
        except School.DoesNotExist:
            raise Exception("School does not exist".format(id))

        school.archived = True
        school.save()
        return DeleteSchoolMutation(success=True)

When I carry out the delete mutation as such:

mutation {
  deleteSchool(id: "U2Nob29sVHlwZToy") {
    success
  }
}

I get the following results;

{
  "data": {
    "deleteSchool": {
      "success": null
    }
  }
}

The same goes for the update mutation. These are the versions I am using incase if it helps:

django==4.0.8
graphene-django==3.0.0
django-filter==22.1
django-graphql-jwt==0.3.4
graphene-file-upload==1.3.0

Solution

  • The mistake is in the mutate method. The mutate method requires 3 initial arguments cls, root, and info before the custom user arguments

    Therefore this Delete Mutation:

    class DeleteSchoolMutation(graphene.Mutation):
        success = graphene.Boolean()
    
        class Arguments:
            id = graphene.String(required=True)
    
        @classmethod
        def mutate(self, info, id, **kwargs):
            # Delete School
    

    Would become:

    class DeleteSchoolMutation(graphene.Mutation):
        success = graphene.Boolean()
    
        class Arguments:
            id = graphene.String(required=True)
    
        @classmethod
        def mutate(self, root, info, id, **kwargs):
            # Delete School