How to get the Model ID in the Graphene Django Relay query?
Asked Answered
B

3

9

How to receive the native Model ID that stored in the DB (eg. django model ID) when we are executing the Relay query? The main issue that the Relay defines it's own ID so I'm not sure how can we correctly handle it.

For ex.

query {
  allFuelTypes (codeMatch: "g") {
    edges {
      node {
        id,
        code,
        label
      }
    }
  }
}

will print

{
  "data": {
    "allFuelTypes": {
      "edges": [
        {
          "node": {
            "id": "RnVlbFR5cGVOb2RlOjM=",
            "code": "g",
            "label": "Gas"
          }
        }
      ]
    }
  }
}

Where id is the Graphene Relay ID but I'd like to see the Model ID.

The only one possible way that I see is just to create some alias in the graphene Schema for the Model ID field and manually fetch this ID from the Django Model. But perhaps there is existing some more dynamic way to achieve the same result?

Thanks for any help!

P.S. the implementation of the query isn't important. It's just a dummy demo

Blanketing answered 3/2, 2020 at 13:12 Comment(0)
I
16

This worked for me!

Let's define a simple model:

class Account(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        ordering = ['id']

Now let's define its corresponding Relay Node:

class AccountNode(DjangoObjectType):
    # just add this line
    id = graphene.ID(source='pk', required=True)

    class Meta:
        model = Account
        interfaces = (relay.Node, )

Attach it to you Query:

class Query(ObjectType):
    all_accounts = DjangoFilterConnectionField(AccountNode)

Make your request:

enter image description here

Inflorescence answered 7/7, 2020 at 9:53 Comment(0)
V
6

You can define a custom field for pk, here is an example with user.

from django.contrib.auth import get_user_model
import graphene
from graphene_django.types import DjangoObjectType
from graphene_django.filter.fields import DjangoFilterConnectionField


class UserNode(DjangoObjectType):
    class Meta:
        model = get_user_model()
        interfaces = (graphene.relay.Node,)

    pk = graphene.Int()

    def resolve_pk(self, info):
        return self.pk

class UserQuery(graphene.ObjectType):
    user = graphene.relay.Node.Field(UserNode)
    users = DjangoFilterConnectionField(UserNode)

class Query(UserQuery, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query)

Then you can query like:

query {
  users{
    edges {
      node {
        pk
      }
    }
  }
}

You can check other examples here.

Volitive answered 3/2, 2020 at 14:13 Comment(1)
Hi @pedrobern. Thank you for your answer. I mentioned this solution in my post, but, maybe, there is existing some elegant way how to receive the model id without aliasing this ID and manually resolving it?Blanketing
L
2

It can be easily resolved using a custom node. Like this -

class CustomNode(graphene.Node):
    """
    For fetching object id instead of Node id
    """

    class Meta:
        name = "Node"

    @staticmethod
    def to_global_id(type, id):
        return id

Now you just have to import it into your nodes Interfaces like -

class UserNode(DjangoObjectType):
    class Meta:
        model = get_user_model()
        interfaces = (CustomNode,)

Hope this serves your purpose.

Lelahleland answered 2/5, 2020 at 3:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.