Hello,
I'm a bit new to the whole graphene django dev scene so it might be that I dont have everything right
So I'm working on a project that uses ApolloClient on the frontend and I wanted to get the automatic cache updates working. For that to work, the arguments of the mutation have to be the individual fields of that ObjectType to be mutated. Also it should return the ObjectType directly and not a wrapping of that ObjectType.
Somehow I was unable to get my backend running like this with the current graphene django combination. So I started digging and modified the SerializerMutation from graphene-django a bit. Below is what I came up with so far. Maybe some experts can comment on this. I don't know why the ClientIDMutation is used currently. I skipped that in my implementation and just used graphene.Mutation directly. Well let me know if this is any use or not. In case of the former I would be glad to polish this up and make a pull request.
class MySerializerMutation(graphene.Mutation):
class Arguments:
pass
@classmethod
def __init_subclass_with_meta__(cls, serializer_class=None, output_type=None, lookup_field=None, model_class=None, **options):
serializer_class = serializer_class
for k, v in fields_for_serializer(
serializer_class(), (), (), is_input=True).items():
setattr(cls.Arguments, k, v)
setattr(cls, 'Output', output_type)
if model_class is None:
serializer_meta = getattr(serializer_class, 'Meta', None)
if serializer_meta:
model_class = getattr(serializer_meta, 'model', None)
_meta = SerializerMutationOptions(cls)
_meta.lookup_field = lookup_field
_meta.model_operations = ['update', 'create']
_meta.serializer_class = serializer_class
_meta.model_class = model_class
super(MySerializerMutation, cls).__init_subclass_with_meta__(_meta=_meta, **options)
@classmethod
def get_serializer_kwargs(cls, root, info, **input):
lookup_field = cls._meta.lookup_field
model_class = cls._meta.model_class
if model_class:
if 'update' in cls._meta.model_operations and lookup_field in input:
instance = get_object_or_404(model_class, **{
lookup_field: input[lookup_field]})
elif 'create' in cls._meta.model_operations:
instance = None
else:
raise Exception(
'Invalid update operation. Input parameter "{}" required.'.format(
lookup_field
))
return {
'instance': instance,
'data': input,
'context': {'request': info.context}
}
return {'data': input, 'context': {'request': info.context}}
@classmethod
def mutate(cls, root, info, **input):
kwargs = cls.get_serializer_kwargs(root, info, **input)
serializer = cls._meta.serializer_class(**kwargs)
if serializer.is_valid():
obj = serializer.save()
return obj
else:
errors = [
ErrorType(field=key, messages=value)
for key, value in serializer.errors.items()
]
return cls(errors=errors)
hey @spflueger, when I implemented the serialiser mutation I mistakenly decided to not wrap the returned fields in a new type. I have a custom version of serialiser mutation to fix this, which works similar to what I proposed here: #386
I'll see if I can send the PR soon :)
hey @patrick91
when I implemented the serialiser mutation I mistakenly decided to not wrap the returned fields in a new type
I'm confused about "mistakenly decided to not wrap the returned fields in a new type". Are you talking about your own serializer mutation or about the one in the repo? Because I was not able to get the repo serializer mutation to return just the fields of the object, only the wrapped version. That's why I wrote my own serializer mutation.
Not sure I understood you correctly. So your custom version will fix this by having this flag or switch to allow a wrapped or non-wrapped type return?
Btw, what is the benefit of the ClientIDMutation?
I wrote the implementation of the serialiser mutation and when I did it I wasn't using Apollo yet :)
Not sure I understood you correctly. So your custom version will fix this by having this flag or switch to allow a wrapped or non-wrapped type return?
yes, the flag would be for backwards compatibility mainly, but I guess it is also good to allow users to choose how they want the API to behave
Btw, what is the benefit of the ClientIDMutation?
Not sure to be honest :)
Ah ok, I get it. Your idea sounds good to me. Thanks for the effort!
I think this is related to https://github.com/graphql-python/graphene-django/issues/376
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@spflueger Any news on PR for this?
I thought @patrick91 was trying to make a PR for this. Too be honest, I haven't been coding for this project for months now. I'm still using the code snippet I send above...
Most helpful comment
hey @spflueger, when I implemented the serialiser mutation I mistakenly decided to not wrap the returned fields in a new type. I have a custom version of serialiser mutation to fix this, which works similar to what I proposed here: #386
I'll see if I can send the PR soon :)