3

When implementing GraphQL update mutations with many (here just a and b) optional InputObjectType fields it generates a lot of boilerplate to check if the InputObjectTypes fields have been passed. Is there some idiom which is considered best practice w.r.t. this topic?

# <app>/models.py

from django.db import models

class Something(models.Model):
    a = models.CharField(default='')
    b = models.CharField(default='')


# <app>/schema.py

import graphene
from graphene_django import DjangoObjectType
from .models import Something


class SomethingType(DjangoObjectType):
    class Meta:
        model = Something


class SomethingInput(graphene.InputObjectType):
    # all fields are optional
    a = graphene.String()
    b = graphene.String()


class SomethingUpdateMutation(graphene.Mutation):
    class Arguments:
        id = graphene.ID(required=True)
        something_data = SomethingInput(required=True)

    something = graphene.Field(SomethingType)

    def mutate(self, info, id, something_data):
        something_db = Something.objects.get(pk=id)
        # checking if fields have been passed or not and
        # only change corresponding db value if value has been passed
        if something_data.a is not None:
            something_db.a = something_data.a
        if something_data.b is not None:
            something_db.b = something_data.b
        something_db.save()
        return SomethingUpdateMutation(something=something)


class Mutation(object):
    # project schema inherits from this class
    something_update_mutation = SomethingUpdateMutation.Field()
thinwybk
  • 4,193
  • 2
  • 40
  • 76

1 Answers1

1

You can do this:

def mutate(self, info, **kwargs):
    user = info.context.user
    for k, v in kwargs.items():
        user.k = v
    user.save()
    return UpdateUser(user=user)

But still, I'm also finding some elegant way to do it.

But, if user wanna remove the content from the field, then what will you do since you are checking !None. IMO, the best practice, when we update a data we send all the data with the updated fields. So we don't need to check, is something empty or not.

abheist
  • 77
  • 5
  • 1
    I don't think it's the best practice to send all data when updating a model. The reason is that you'd have to store all the model's data in the system which interacts with your GraphQL API e.g. a client in the frontend code. This means you'd have to either query all model data before someone changes data in a form OR you'd have to store the model data in the frontend. The later is even worse. Having to store state in another place than the backend is bad. – thinwybk Feb 05 '21 at 13:05
  • 3
    You need to use `setattr(user, k, v)` here, `user.k = v` creates a new attribute `k` on the `user` object (`django.db.models.Model` instances are mutable) – 42point2 Jun 29 '21 at 12:56