Skip to content

Can I customise how the global id is created? #294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hgylfason opened this issue Oct 19, 2017 · 3 comments
Closed

Can I customise how the global id is created? #294

hgylfason opened this issue Oct 19, 2017 · 3 comments

Comments

@hgylfason
Copy link

Short story:

Can I alter how the global id is generated based on the arguments given in a query? If so where would be the right place to do so?

Long story:

I am faced with a problem where I need different states of the same node to coexist in my store in the frontend (using Apollo). This is a problem as the global id is used to identify a node and that id is the same for all the states of a particular node.

I think it's best to explain this through an example.

Here I have a query for an asset. If "at_date" is one of the arguments then
the state of the asset at that time is returned instead. The problem with this is that
the global id doesn't change and my client therefore thinks that the current state and the older state of the asset are the same and hence they won't be stored separately.

What I would like to do is to add "at_date", if defined, alongside the
"type" and "id" to generate the global id to ensure that the global id becomes unique across different states of the same asset. Is that possible?

import graphene
from graphene_django import DjangoObjectType
from graphql_relay import from_global_id
from assets import models

...

class Asset(DjangoObjectType):
    class Meta:
        model = models.Asset
        interfaces = (graphene.relay.Node, )

class Query(graphene.AbstractType):
    asset = graphene.Field(
        Asset,
        id=graphene.ID(),
        at_date=graphene.String(description='The point in time which the state '
                                            'is evaluated.'))

    def resolve_asset(self, args, context, info):
        qs = models.Asset.objects

        id = args.get('id')
        if id is not None:
            model, pk = from_global_id(id)
            qs = qs.filter(pk=pk)

        instance = qs.get()

        at_date = args.get('at_date')
        if at_date is None:
            return instance

        return instance.resolve_old_state(at_date)
@japrogramer
Copy link

you can define your own id field, so that it takes the extra argument that you are looking for
than use resolve_id to generate the actual value for the field. Yes it is possible.

@hgylfason
Copy link
Author

@japrogramer , good idea. I can probably create an interface for this behaviour.
Would this work for relations e.g. if the asset in the example above had a relation to an organisation. Would the resolver for the organisation have access to the arguments given to the "asset" query?

@japrogramer
Copy link

you would of course modify get_node also and supporting methods http://docs.graphene-python.org/en/latest/relay/nodes/
For the relations I recommend using a ConnectionField you could than have assess to those variables in resolve methods in the connection and thus the edges. and possibly annotate the nodes to have access to them in the nodes

I tried something similar here
graphql-python/graphene#573

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants