Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 447
Velidan Avatar asked Feb 03 '20 13:02

Velidan


Video Answer


3 Answers

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

like image 52
Juan-Kabbali Avatar answered Oct 11 '22 18:10

Juan-Kabbali


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.

like image 40
pedrobern Avatar answered Oct 11 '22 20:10

pedrobern


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.

like image 2
Ameya Marathe Avatar answered Oct 11 '22 19:10

Ameya Marathe