Graphene-django: How to write update function with graphene-django

Created on 14 Aug 2018  路  6Comments  路  Source: graphql-python/graphene-django

I am imprementing update function of the attribute of User with graphene-django

Of course we implement it as a mutation, mutate can be written with kwargs,
We have to define all elements in Arguments class and field settings after all.

  1. how can we update only one element, for example?

    Currently, I can not update without passing all elements

  2. How can I write these well with kwargs?

    I want to change that there are three rewriting places for changing elements.(setting filed, arg, return)

thank you

class UpdateUser(graphene.Mutation):
    user = graphene.Field(UserType)
    username   = graphene.String(required=True)
    first_name = graphene.String(required=True)
    last_name  = graphene.String(required=True)
    #???password   = graphene.String(required=True)
    email      = graphene.String(required=True)


    class Arguments:
        username   = graphene.String(required=True)
        first_name = graphene.String(required=True)
        last_name  = graphene.String(required=True)
        #???password   = graphene.String(required=True)
        email      = graphene.String(required=True)


    @login_required
    def mutate(self, info, **kwargs):
        user = info.context.user
        for k, v in kwargs.items():
            user.k = v
        # user.set_password(password)
        user.save()
        return UpdateUser(username=username,
                      first_name=first_name,
                      last_name=last_name,
                      email=email )

Most helpful comment

class UserInput(graphene.InputObjectType):
    username   = graphene.String(required=False)
    first_name = graphene.String(required=False)
    last_name  = graphene.String(required=False)
    password   = graphene.String(required=False)
    email      = graphene.String(required=False)


class UpdateUser(graphene.Mutation):
    user = graphene.Field(UserType)

    class Arguments:
        user_data = UserInput(required=True)

    @login_required
    def mutate(self, info, user_data=None):
        user = info.context.user

        for k, v in user_data.items():
            if (k == 'password') and (v is not None):
                user.set_password(user_data.password)
            else:
                setattr(user, k, v)

        try:
        user.full_clean()
        user.save()
        return UpdateUser(user=user)
    except ValidationError as e:
        return UpdateUser(user=user, errors=e)

All 6 comments

excuse me馃槶

class UserInput(graphene.InputObjectType):
    username   = graphene.String(required=False)
    first_name = graphene.String(required=False)
    last_name  = graphene.String(required=False)
    password   = graphene.String(required=False)
    email      = graphene.String(required=False)


class UpdateUser(graphene.Mutation):
    user = graphene.Field(UserType)

    class Arguments:
        user_data = UserInput(required=True)

    @login_required
    def mutate(self, info, user_data=None):
        user = info.context.user

        for k, v in user_data.items():
            if (k == 'password') and (v is not None):
                user.set_password(user_data.password)
            else:
                setattr(user, k, v)

        try:
        user.full_clean()
        user.save()
        return UpdateUser(user=user)
    except ValidationError as e:
        return UpdateUser(user=user, errors=e)
mutation {
  updateUser(userData: {username: "yes", email: "[email protected]", firstName: "k", lastName: "k"}){
    user {
      username
      email
      firstName
      lastName
    }
  }
}

thanks for posting solution. I'd been looking for the solution to the same problem. But Im wondering if this is the only solution to the problem. Is there not a more elegant way to do it?

@leiwu123 Seems like the only way to reference a model doing mutations is to use relay like in the starwars example. Pretty ugly to have to update fields in both places all the time. Documentation on this kind of thing is non-existent.

If you are using django forms an alternative is to override the form clean function:

    def clean(self):

        # If created by not set do not override with blank value, default to existing value.
        if not self.cleaned_data.get("created_by"):
            self.cleaned_data["created_by"] = self.instance.created_by
Was this page helpful?
0 / 5 - 0 ratings

Related issues

BrianChapman picture BrianChapman  路  3Comments

flame0 picture flame0  路  4Comments

Eraldo picture Eraldo  路  3Comments

timothyjlaurent picture timothyjlaurent  路  3Comments

mraak picture mraak  路  3Comments