Back
Jan 9, 2017

How to Use GraphQL with Django

Rostyslav Stekh
Rostyslav Stekh

In this article, we will describe on how to use GraphQL with Django. In this guide, you will see code sample and examples of implementation for Python.

Example on how to use GraphQL with Django

Let’s say that you have the Category and Ingredient models:

from django.db import models


class Category(models.Model):
    name = models.CharField(max_length=100)

    def str(self):
        return self.name


class Ingredient(models.Model):
    name = models.CharField(max_length=100)
    notes = models.TextField(null=True, blank=True)
    category = models.ForeignKey(Category, related_name='ingredients')

    def str(self):
        return self.name

First, you need to install Graphene – the GraphQL implementation for Python. You can set up it by using ‘pip install graphene[django]’ with the Django extensions. I would also recommend installing it with the Graphiql ‘pip install graphiql_django’ as it’s a convenient and a simple user interface for testing GraphQL queries.

Once you've installed the GraphQL implementation for Python and ready to go, create schema.py for 'graphene':

From ingredients.models import Category, Ingredient
from graphene import ObjectType, Node, Schema
from graphene_django.fields import DjangoConnectionField
from graphene_django.types import DjangoObjectType

class CategoryNode(DjangoObjectType):

    class Meta:
        model = Category
        interfaces = (Node, )

class IngredientNode(DjangoObjectType):

    class Meta:
        model = Ingredient
        interfaces = (Node, )

class Query(ObjectType):
    category = Node.Field(CategoryNode)
    all_categories = DjangoConnectionField(CategoryNode)

    ingredient = Node.Field(IngredientNode)
    all_ingredients = DjangoConnectionField(IngredientNode)

schema = Schema(query=Query)

Also, you have to add graphql django to 'urls.py':

from django.conf.urls import url
from django.contrib import admin

from graphene_django.views import GraphQLView

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^graphql', GraphQLView.as_view(graphiql=True)),
]

Now you can go to localhost:8000/graphql and start testing queries in ​django graphql. GraphQL also gives great hints if you add a description in the schema definition.

So in the GraphQL server for /ingredient/some_id, we have written a view to return a serialized version of the ingredient with id=some_id. It might return something like this:

{
  "name":"some name",
  "notes":"some notes"
}

Now if you want to get the ingredients of the category in REST, this can be implemented in different ways like /ingredients/?category=some_id or /category/some_id/ingredients/. And yet in both cases, we have to write an additional code.

GraphQL solves this easily with a query schema help, where you define how and in what way a field will be returned. So the GraphQL query will look like this:

query {
category(id:some_id){
ingredients {
edges {
node {
id
name
notes
}
}
}
}
}
 

As you can see, the category field takes a parameter id which has a value of some_id. As a result of this query, the server will return from the database a category with id=some_id and all the ingredients with the id, name and notes fields of this category and will send to the client.

In this case, the id, name and notes data for the fields are taken from a Django model, which was described above. We use the "Node" built-in UI which automatically resolves the field models and therefore, you don’t need to describe the processing of each field.

As well, the user interface automatically generates static id for their connection ‘nodes’ and returns them to the ‘id’ field, and it is possible to make queries by using them. However, this functionality can be replaced, so you return the id object from the database.

I will not describe this process in the article, as you can read about it in the official documentation. As you can see, to show specific data with the id help, you can use ‘Node.Field’, which receives a resolved connection model. And in turn, ‘DjangoConnectionField’ returns all data from the model.

Also, at the first sight, it’s hard to understand the ‘edges’ and ‘node’ fields. But these are standard fields that connect nodes and display information. You can read more here.

What is great here is that GraphQL can help to disconnect your backend from your web interface. Also, that solves issues of inefficient communication between the API and the frontend team. The frontend team gets to decide what information to query for and where to show it. In turn, the backend team is only responsible for "how and what data to display in the field", allowing adding new changes and then turn them on whenever it’s appropriate to do so in the web interface.

Let's assume you are going to develop a mobile frontend for this API, and you need to display all the products in a ‘Category’, but without the ‘notes’ field. Instead of writing a new endpoint or modifying the existing one (which might lead to the problems), you can simply write:

query {
category(id:some_id){
ingredients {
edges {
node {
id
name
}
}
}
}
}
 

And the GraphQL server request would return:

{
  "data": {
    "category": {
      "ingredients": {
        "edges": [
          {
            "node": {
              "id": "some_id",
              "name": "some_name"
            }
          },
          {
            "node": {
              "id": "some_id",
              "name": "some_name"
            }
          }
        ]
      }
    }
  }
}

With GraphQL, you can develop and implement any changes in the API without worrying about breaking client applications. This gives us an effective way of making the data serialization and certainly resolves the field in the backend.

For fields and objects you can add custom configurations. For example, you can add different verification rules to allow the user to see his own posts or comments, or do additional filtering. This all can be found in the official documentation. However, I'll show you a short example of filtering where you can take the existing code and modify it:

from graphene_django.filter import DjangoFilterConnectionField
# ...

class CategoryNode(DjangoObjectType):

    class Meta:
        # ...
        filter_fields = ['name', 'ingredients']


class Query(ObjectType):
    # ...
    all_categories = DjangoFilterConnectionField(CategoryNode)
    # ...

Here, instead of DjangoConnectionField, we use a special filter for the field DjangoFilterConnectionField, which will filter the data for the given fields ['name', 'ingredients']. Now, we make a query to the category and show all the ingredients, but will filter by category name = some_name:

query {
allCategories(name:"some_name"){
edges{
node{
ingredients{
edges{
node{
name
}
}
}
}
}
}
}
 

What we would get back is:

{
    "data": {
        "allCategories": {
            "edges": [
                {
                    "node": {
                        "ingredients": {
                            "edges": [
                                {
                                    "node": {
                                        "name": "some_name"
                                    }
                                },
                                {
                                    "node": {
                                        "name": "some_name"
                                    }
                                }
                            ]
                        }
                    }
                }
            ]
        }
    }
}

GraphQL is a very powerful library, which is not difficult to understand. GraphQL will help to write simple and clear REST API to suit every taste and meet any requirements.

Hope this short overview of GraphQL helps you understand the basics. You can read more on graphene python tutorial.

More thoughts

Feb 12, 2020Technology
5 Best Payment Gateways For 2020

We reviewed the best payment gateways in 2020. Here’s our comparison of their features, advantages, and disadvantages.

Vladimir Sidorenko
Vladimir Sidorenko
Sep 21, 2020Technology
How to Optimize Django ORM Queries

Django ORM is a very abstract and flexible API. But if you do not know exactly how it works, you will likely end up with slow and heavy views, if you have not already. So, this article provides practical solutions to N+1 and high loading time issues. For clarity, I will create a simple view that demonstrates common ORM query problems and shows frequently used practices.

Alexey Demianenko
Alexey Demianenko
Jan 12, 2017Technology
Making Custom Report Tables Using AngularJS and Django

In this article I will tell you how to create an interactive interface with a widely customized visual look and different filtering to view reports.

Pasha Volkov
Pasha Volkov
Jan 10, 2017Technology
How To Use GraphQL with Angular 2 (with Example)

​In this article we will tell you about the basics of working with GraphQL in Angular 2 environment with detailed example.

Alexandr Selyanov
Alexandr Selyanov
Jun 25, 2011Technology
Ajax blocks in Django

Quite often we have to write paginated or filtered blocks of information on page. I created a decorator that would automate this process.

Vladimir Sidorenko
Vladimir Sidorenko
May 12, 2010Technology
Twitter API, OAuth and decorators

In my current project I had a task to use twitter API. Twitter uses OAuth for authentication, which is pretty dreary. To avoid fiddling with it all the time, I've moved authentication to decorator. If key is available - nothing happens, just view is launched as usual. It's convenient that there's no need for additional twitter settings in user profile. Code is in article.

Vladimir Sidorenko
Vladimir Sidorenko