Graphene-django: Retrieve authenticated user without supplying ID! when using relay

Created on 23 Mar 2017  路  7Comments  路  Source: graphql-python/graphene-django

Hi there! Thanks for the awesome library.
I'm having a little problem I cant seem to find any documentation for.
With a simple schema like this, I can ensure return the details for the authenticated user:

from django.contrib.auth import models
class UserType(DjangoObjectType):
    class Meta:
         model = models.User

class Query(ObjectType):
    user = graphene.Field(UserType)

    def resolve_user(self, args, context, info):
       if context.user.is_authenticated:
          return context.user

schema = graphene.Schema(query=Query)

So I can do a query like:

query {
  user {
    firstName
    lastName
    email
  }
}

and it returns the details for the currently-logged in user (i.e. me).

Now I'd like to set it up for use with relay, so I do this:

from django.contrib.auth import models
class UserNode(DjangoObjectType):
    class Meta:
         model = models.User
         interfaces = (relay.Node, )

class Query(AbstractType):
    user = relay.Node.Field(UserNode)

    def resolve_user(self, args, context, info):
       if context.user.is_authenticated:
          return context.user

Now when I run the same query, I get

 `"Field \"user\" argument \"id\" of type \"ID!\" is required but not provided.",`

Is there any way to avoid having to supply relay ID?
Am I right in thinking overriding get_node will not help much, since id is a required argument?

Most helpful comment

Thanks @BossGrand, This tripped me up for a while trying to access and filter django object id's using relay.

It would be great if the documentation was updated to show using Relay with DjangoFilterConnectionField(Node) for returning (and paginating) a set of results and then graphene.Field(Node) for accessing a single result with access to the underlying database model id.

All 7 comments

@JamesRamm

class Query(AbstractType):
    user = relay.Node.Field(UserNode)

should be

import graphene
class Query(AbstractType):
    user = graphene.Field(UserNode)

In general when defining graphene types, you will use graphene.field

@BossGrand
Documentation seems to state that relay.Node.Field should be used when using relay:

http://docs.graphene-python.org/en/latest/relay/nodes/#node-root-field

Will using graphene.Field not break compatibility with the relay library?

it won't, I use relay and I never use relay.Node.Field

I don't fully understand that bit of documentation. if you read the link below a root node has to be named node and is something that you probably don't need to worry about.

https://facebook.github.io/relay/graphql/objectidentification.htm

Just give graphene.Field a shot and let me know if it doesn't work

I have

class ChannelNode(DjangoObjectType):
    class Meta:
        model = Channel
        filter_fields = {'name': ['exact', 'icontains', 'istartswith'],
                         'customer': ['exact', 'icontains', 'istartswith']}
        interfaces = (relay.Node,)
        description = "This is a Channel Node"
class Query(AbstractType):
    channel = Field(ChannelNode)

    def resolve_channel(self, args, context, info):
        id = args.get('id')
        if id is not None:
            return Channel.objects.get(pk=id)
        return Channel.objects.first()

Using just field i get this when i query :

channel(id:1) {
name
}

"message": "Unknown argument \"id\" on field \"channel\" of type \"RootQuery\"."

Is this normal?

ok i found the solution.

channel = Field(ChannelNode)

should be
channel = Field(ChannelNode, id=graphene.Int())

seems like, if we use relay, we always need to pass the correct "id", or it won't fire anything.
I'm doing a authorization test with restframework jwt. I defind a "get_node" method, if I don't pass the id, "get_node" method doesn't execute.

If we use authenticated user, we don't need the "ID" at all.

Thanks @BossGrand, This tripped me up for a while trying to access and filter django object id's using relay.

It would be great if the documentation was updated to show using Relay with DjangoFilterConnectionField(Node) for returning (and paginating) a set of results and then graphene.Field(Node) for accessing a single result with access to the underlying database model id.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BrianChapman picture BrianChapman  路  3Comments

Northshoot picture Northshoot  路  4Comments

licx picture licx  路  3Comments

timothyjlaurent picture timothyjlaurent  路  3Comments

eyalch picture eyalch  路  3Comments