question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

get_node is not called on related objects

See original GitHub issue

Currently get_node is not called on related models. i.e.

class Customer(models.Model):
    display_name = models.CharField()
    ....

class Member(models.Model):
    customer = models.ForeignKey(Customer)
    ....
class Customer(DjangoObjectType):
    class Meta:
        model = models.Customer
        filter_fields = []
        interfaces = [graphene.Node]

    @classmethod
    def get_node(cls, info, id):
        print('NEVER CALLED')
        return None

Then querying with

member(id:"...") {
    customer {
        id
    }
}

Does not result in get_node being called. this is because get_node is only called on Relay Nodes. However relay nodes expect an ID to be passed in via GraphQL. Instead I would like the get_node to be called with the id for the related object.

If this support was added it means you can add per-object level auth.

Furthermore as get_node calls get_queryset, all you would have to do is to filter out all the objects a user isn’t allowed to access i.e.

class Customer(DjangoObjectType):

    @classmethod
    def get_queryset(cls, queryset, info):
        return queryset.filter(admins__in=[info.context.user])

For example lets say Im allowed to see a list of Members, some of those Members are not under the Customer that I am an admin of. However I should still be able to interact with them, as they have some other relationship to my Customer. Maybe the Member is related to another Member under my Customer, and I can access them via that path. However I don’t want to to give an admin the ability to view other Customers. This would achieve that.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:4
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
McPocommented, Sep 17, 2019

class DjangoModelField(graphene.Field):

    @staticmethod
    def model_resolver(django_object_type, resolver, root, info, **args):
        id_field_name = '%s_id' % to_snake_case(info.field_name)
        id_field_value = getattr(root, id_field_name)
        return django_object_type.get_node(info, id_field_value)

    def get_resolver(self, parent_resolver):
        if issubclass(self.type, DjangoObjectType):
            return partial(self.model_resolver, self.type, parent_resolver)
        return super(DjangoModelField, self).get_resolver(parent_resolver)

The above accomplishes that. Note this will remove any optimisation of select/prefect_related(), as we hit the DB each time. However I don’t believe there is any other performance hit if youre not using selected/prefetch_related, as Django still has to access the DB when following the related model. I still need to verify this though

We could possibly accommodate for the related model already having been loaded by checking root._state.fields_cache, however if its preloaded we wouldn’t be able to use get_node to check if the person is authorised to view it without hitting the DB again anyway.

The method used, here is similar to customising the Django RelatedManager for the Model.

Ive made this an Issue instead of PR, as Im still not familiar enough with this library to know of all the gotchas, so figured its best that this is something people opt into. Although I’ll be looking at a way to make this the default behaviour for myself. Maybe subclass DjangoObjectType or something

0reactions
stale[bot]commented, Jul 16, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

get_node method is not called - graphene python
I am experiencing an issue with get_node method in a django object type definition. The method doesn't seem to be called in my...
Read more >
Babylon.js find node By Name "I can't find the node" - Questions
So i find it odd that it doesn't work… getNodeByName iterates all other types of nodes - Babylon.js/scene.ts at master · BabylonJS/Babylon.js ·...
Read more >
Node - Oracle Help Center
Returns an array of NodeType objects representing the mixin node types assigned to this node. Node · getNode(java.lang.String relPath). Returns the node at...
Read more >
CSNODE Quick Start Guide - OpenText Forums
All actions (node and role) are called in the exact same manner; ... NOTE: Objects in OScript are not deleted when they go...
Read more >
Solved In our LLList class from lecture, the worst case for
Because the new field – which we have called last in the diagram above – holds a ... In such cases, getNode should...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found