graphene-django icon indicating copy to clipboard operation
graphene-django copied to clipboard

Using SerializerMutation with Relay

Open dan-klasson opened this issue 6 years ago • 8 comments

I'm overriding mutate_and_get_payload to convert the global ID to PK:


class BaseSerializerMutation(SerializerMutation):

    class Meta:
        abstract = True

    @classmethod
    def mutate_and_get_payload(cls, root, info, **input):

        model = cls._meta.serializer_class.Meta.model

        for field, value in input.items():

            if not hasattr(model, field):
                continue

            model_field = model._meta.get_field(field)

            # convert relay ID to PK
            if isinstance(model_field, (AutoField, ForeignKey)):
                _, input[field] = from_global_id(value)

        return super().mutate_and_get_payload(root, info, **input)

Then I also need to tell DRF that the global ID is not an integer:

from rest_framework import serializers


class BaseModelSerializer(serializers.ModelSerializer):
    id = serializers.CharField(required=False)

Ideally this should already be supported by graphene-django. Perhaps have a RelaySerializerMutation and a RelayModelSerializer? I can create a PR if you're OK with adding this.

dan-klasson avatar Aug 02 '19 08:08 dan-klasson

@dan-klasson a PR would be welcome!

jkimbo avatar Aug 02 '19 12:08 jkimbo

@jkimbo

Before creating a PR for this I wanted to make it support m2m fields as well. But I ran into some issues.

This is the code I came up with.

            model_field = model._meta.get_field(field)

            # convert relay ID to PK
            if isinstance(model_field, (AutoField, ForeignKey)):
                _, input[field] = from_global_id(value)
            elif isinstance(model_field, ManyToManyField):
                values = ast.literal_eval(value)
                input[field] = [from_global_id(val)[1] for val in values]

        return super().mutate_and_get_payload(root, info, **input)

When passing in the ids as a list. The value of value is not deserialized and is not valid JSON. Hence the use of ast.literal_eval. Other than that workaround, it also returns this:

'memberLevels': '<QuerySet [<MemberLevel: level 2>]>'

dan-klasson avatar Aug 06 '19 02:08 dan-klasson

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.

stale[bot] avatar Oct 05 '19 06:10 stale[bot]

@dan-klasson did you have any updates on this issue?

jkimbo avatar Dec 27 '19 14:12 jkimbo

This PR should go further。

The RelaySerializerMutation should:

  • auto cast serializer's id field to ID type.
  • have three fields: CreateField/UpdateField/DeleteField
  • in UpdateField: the arguments should all be optional, except id

thomaszdxsn avatar Jan 17 '20 10:01 thomaszdxsn

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.

stale[bot] avatar May 16 '20 10:05 stale[bot]

That bot really is the scourge of this repository. There are multiple Issues made (and closed) for this particular problem, but I can't find any actual solutions that have been made. Can anybody point me (and no doubt countless others) to a solution to this problem, or perhaps to a single official Issue in which it's being tracked and/or worked on? Apologies for the tone, but I'm becoming a bit frustrated with chasing this around all over the place!

flyte avatar Jul 09 '20 10:07 flyte

Any news?

heckad avatar Jul 15 '23 20:07 heckad