strawberry-django-plus icon indicating copy to clipboard operation
strawberry-django-plus copied to clipboard

Need help on custom relay ID resolution

Open ashishnitinpatil opened this issue 3 years ago • 2 comments

Hi, thank you for the amazing lib. I am implementing relay.Node for several of my django models and I was wondering if there was an easy way to replace id: GlobalID! with a custom resolver, e.g. id: str! where the id resolves to a unique string field on the model. This is so that the IDs which are being used in front-end look more neat and they don't leak the database model ids.

e.g.

# model
class Order(models.Model):
    number = models.Charfield(unique=True)

# type
@gql.django.type(Order)
class Order(relay.Node):
     id: str!
     number: gql.auto

So, instead of getting id as "T3JkZXI6MQ==" (base64 of Order:1) for the instance Order(id=1, number="2022-06-07-001"), we could get something like 2022-06-07-001.

ashishnitinpatil avatar Jun 07 '22 16:06 ashishnitinpatil

Hi @ashishnitinpatil ,

You can change the attribute that is used to retrieve the id using id_attr or even by defining your own resolve_id

Now, if I understood correctly, you want to also change how it is serialized, so instead of being serialized as a base64 of <Type>:<Id> you would only want <Id>? That might be problematic for the following reason:

The globalid should be something unique and that you can usually retrieve the object back by having just it. For example, if I have an object with id 2022-06-07-001 as you described, for which type is it? Is it an OrderType, an UserType or even a ProductType? That is the reason that usually the type is serialized together.

Having said that, you can probably create a custom directive to use on GlobalID scalars, which would retrieve those and get you the id directly. For example, you could use it like this on the client:

order {
  id
  extractedId: id @extractGlobalId
}

In the example bellow, the id still is the globalid as a base64, but the extractedId would be the id that your directive returned, which can be implemented to return the id directly.

What do you think of those approaches? Of am I missing something on what do you want to do?

bellini666 avatar Jun 12 '22 15:06 bellini666

Thanks for the helpful response @bellini666 !

I tried defining the id_attr on my type earlier, but it doesn't work as intended, maybe overriding the resolve_id might help. I'll try that.

Your understanding is mostly correct, and I completely get why one should ideally use the combination of <Type>:<Id> but the reason I would prefer just <Id_attr> (in my case number) is that the frontend URLs which use the id would look much better and be human readable, not to mention the concern of revealing the database autoincrementing ID. Which is why, I don't mind throwing errors when a different type's ID is passed to the APIs that use the <Id_attr> for resolving objects instead of usual <Type>:<Id>.

Hope I'm little more clear.

ashishnitinpatil avatar Jun 13 '22 10:06 ashishnitinpatil