Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a custom id with Graphene and Relay?

I've implemented graphql and I'm migrating to relay. I already have a uuid for every table and that is named 'id'. And my application I found this github thread that talks about possibly changing the spec but it feels like a rabbit hole.

Is there a simple way that I can use my own custom id with relay?

like image 675
mucle6 Avatar asked Oct 21 '25 15:10

mucle6


1 Answers

If you've already implemented a default relay endpoint then you should have some TableNameNode classes that have a Meta nested class, and a seperate Query class.

    class ExampleTableNameNode(DjangoObjectType):
        class Meta:
            model = ExampleTableName
            interface = (relay.Node,)
    
    class Query(object):
        example_table_name = relay.Node.Field(ExampleTableNameNode)
        all_example_table_names = DjangoFilterConnectionField(ExampleTableNameNode)
    
        def resolve_example_table_name(self, info, **kwargs):
            pass
    
        def resolve_all_example_table_names(self, info, **kwargs):
            pass

The interface = (relay.Node,) is what defines:

  1. How the ids are being generated
  2. How they are used to fetch data

If we create a relay.Node subclass that redefines these two features then we can use our custom ids.

    class CustomNode(relay.Node): 
        class Meta:
            name = 'Node'
    
        @staticmethod
        def to_global_id(type, id):
            #returns a non-encoded ID
            return id
    
        @staticmethod
        def get_node_from_global_id(info, global_id, only_type=None):
            model = getattr(Query,info.field_name).field_type._meta.model
            return model.objects.get(id=global_id)

Here we implemented two functions, to_global_id, and get_node_from_global_id. The line model = ... is a bit of magic to go from the graphql query table name to the actual model. If that doesn't work you'll just need to make a dictionary to go from something like example_table_name to the actual ExampleTableName django model.

Once you do that you'll have to replace the two references to relay.Node with CustomNode like so.

    class ExampleTableNameNode(DjangoObjectType):
        class Meta:
            model = ExampleTableName
            interface = (CustomNode,)
    
    class Query(object):
        example_table_name = CustomNode.Field(ExampleTableNameNode)
        all_example_table_names = DjangoFilterConnectionField(ExampleTableNameNode)
    
        def resolve_example_table_name(self, info, **kwargs):
            pass
    
        def resolve_all_example_table_names(self, info, **kwargs):
            pass

The answer is in the graphene docs. I read them when I was implementing graphene and relay but there is so much to learn at once that it's easy to read through custom node section and not remember later that you need to do a custom node solution.

like image 87
mucle6 Avatar answered Oct 26 '25 19:10

mucle6