Exposing properties with Graphene Django

23 May 2017
The other missing guide

Graphene Django is an easy to use library for writing GraphQL APIs within Django. But some of the documentation for Graphene is less than great.

When I was learning Graphene Django, I originally found it very hard to expose an @property value of my model to the GraphQL API. This article will look into how to do that, and also why it works.

Ctrl-C Ctrl-V

Say you have a Poll object, and you added a URL property:

class Poll(models.Model):

  ...

  @property
  def url(self):
      return 'https://pollsite/polls/' + id

Then you can simply add a line to specify its existence in the schema:

class PollType(DjangoObjectType):
    class Meta:
        model = models.Poll
        interfaces = (relay.Node,)

    # This is it, so simple and so functional:
    url = graphene.String()

That's it. Just use the form property_name = graphene.​DataType(​)​. You can even use more fancy datatypes, like a graphene.​List(​graphene.​Int(​))​. There is a good reference to check it out.

So why does that work?

First, we need to understand the resolver of the property. By default, the resolvers perform a getattr lookup on the object. This means it would like be this if we were to write it manually:

    url = graphene.String()
    def resolve_url(self, args, context, info):
      return self.url

But that code looks stupid! Isn't the url attribute the graphene.​String(​)​? Isn't that code broken?

Well the self in a resolver doesn't represent an instance of the class. Or maybe it does. Anyway; Graphene is a festival of metaclass programming. So the self object is really the Django object, not your graphene object! Once I found that out, it all started to make a lot more sense to me.

Conclusion

Well, that's a very quick dive into the weird and wonderful world of the Graphene framework. Metaclass magic hey!

If you enjoy these random Graphene tips, make sure to subscribe below.