Tigran Bayburtsyan Cofounder and CTO at Hexact, Inc. Software scalability expert!

Django and GraphQL: Demo project with Graphene

5 min read 1475

Django GraphQL Project Graphene

Editor’s note: This article was updated on 3 May 2022 to reflect the most recent versions of GraphQL and Django and to better detail the GraphQL and Django demo project, including the use of Graphene for integration.

For the past eight years or so, Django has been the most effective framework for making quick web applications, API endpoints, or admin panels for other applications.

One of the biggest advantages of Django is its ability to enable users to write less code and get started quicker, especially if you’re including an admin panel and a fully manageable database migration process as base functionality.

Django REST Framework, an external toolkit, makes it easy to build API endpoints. It basically wraps full CRUD API around the Django Model with just a few lines of code.

This means that building any basic CRUD API with Django helps to keep more of a development focus on UI parts, which are key elements of all software products.

Similarly, GraphQL aims to automate backend APIs by providing type strict query language and a single API Endpoint where you can query all information that you need from UI and trigger actions (mutations) to send data to the backend.

My journey with GraphQL started with Facebook’s API, where GraphQL comes from.

Naturally, GraphQL is considered to be very close to the JavaScript world, mostly because browser-based apps are the first adopters of that technology.

That’s why my first GraphQL server+client was done in Node.js and React.js. After having the first app built on top of GraphQL API, I started to use it exclusively for my Web-based projects.

In this article, I’ll review the advantages of GraphQL and GraphQL Subscriptions. I’ll also build a sample project using GraphQL and Django to demonstrate how powerful this combination can be for web development. I’ll use Graphene for the integration.

Jump ahead:

Advantages of GraphQL

As you may have guessed, there is a library for Django to support GraphQL called Graphene-Django, which is very similar to the Django REST Framework. However, there are significant differences between Django REST and Django with GraphQL.

The key difference lies in UI usability: with a REST API, you’re getting endless URLs with specific parameter names where you have to check types and specific values.

Meanwhile, with GraphQL you’re defining mutations similar to the code below and getting strictly defined variable names and types, which become part of an automatic GraphQL type validation.



type Mutation {
  userLogin(email: String!, password: String!): UserLoginResponse
}

type UserLoginResponse {
  token: String
  error: Boolean
  message: String
}

GraphQL also comes with another bonus packaged inside its type system: it automatically generates documentation where you can get available queries and mutations with their parameters/return types.

Django REST also generates some form of documentation, but it is not as usable as the GraphQL Playground.

If you think this type of interface is available for all kinds of GraphQL endpoints, you’re wrong — this is only available in development mode servers. Although, you can download software like GraphQL Playground standalone and manually configure it for any public GraphQL endpoint.

In terms of security, having one API endpoint is naturally more manageable than having hundreds of them — especially when you consider the fact that GraphQL automatically keeps specific type rules and won’t allow requests with incorrect parameter names or values.

Django ❤️ GraphQL

Let’s build a basic project with Django and GraphQL just to demonstrate how powerful this setup can be. On one hand, you’re getting easy CRUD management with database. On the other hand, you’re getting a very powerful API query language with a single endpoint.

Project setup

  • Open up an empty directory in your IDE terminal or standalone terminal emulator
  • Create a virtual environment: python -m venv venv
  • Activate the virtual environment: source ./venv/bin/activate
  • Install Django and Graphene: pip install django graphene_django
  • Create a new Django project: django-admin startproject graphqlpractice
  • cd into the upper graphqlpractice directory

Creating the models

Now, let’s create and define our models. Create a new Django app django-admin startapp postusers, and register the app in settings.py like so:

INSTALLED_APPS = [
...
"postusers.apps.PostusersConfig"
]

Next, define the models in postusers/models.py like so:

from django.db import models
class Author(models.Model):
    name = models.CharField(max_length=100)


    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField(maxlength=100)
    body = models.TextField()
    author = models.ForeignKey(
        Author, relatedname="posts", on_delete=models.CASCADE
    )
    def str(self):
        return self.title

Now, let’s register the models with the admin panel by adding the following code to postusers/admin.py:

from django.contrib import admin
from .models import Author, Post
admin.site.register(Author)
admin.site.register(Post)

Next, make migrations: python manage.py makemigrations.

N.B., if you get an error regarding force_text this has to do with breaking changes in Django 4; either downgrade to Django 3 or follow the directions here

Now, run the migrations: python manage.py migrate

Create a superuser — python manage.py createsuperuser — and run your server with python manage.py runserver. Then head over to localhost:8000/admin and add a few authors and posts.

Setting up Graphene

Now, let’s set up Graphene, a powerful library that integrates with Django. First, add Graphene to installed apps in /graphqlpractices/settings.py like so:

INSTALLEDAPPS = [
    ...
    'django.contrib.staticfiles',
    "graphenedjango"
    ...
]

Then, add the GraphQL endpoint to /graphqlpractice/urls.py:

from django.contrib import admin
from django.urls import path
from graphenedjango.views import GraphQLView
urlpatterns = [
    path('admin/', admin.site.urls),
    path("graphql", GraphQLView.asview(graphiql=True)),
]

Next, add the following settings.py to identify where your GraphQL schema is located, postusers/schma/schema.py; you will need to make the schema directory and file.

GRAPHENE = {
    "SCHEMA": "postusers.schema.schema"
}

The most interesting part of this project is defining GraphQL types and queries in Python. It’s actually based on your database models, but you can also define custom queries without using Django Models.

Add the following to the postusers/schema/schema.py:

from graphene_django import DjangoObjectType
import graphene
from postusers.models import Post as PostModel
from postusers.models import Author as AuthorModel
class Post(DjangoObjectType):
    class Meta:
        model = PostModel
        fields = ['id', 'title', 'body', 'author']

class Author(DjangoObjectType):
    class Meta:
        model = AuthorModel
        fields = ['id', 'name', 'posts']
    def resolve_posts(self, info):
                return PostModel.objects.filter(author=self)
    @classmethod
    def get_node(cls, info, id):
        return Author.objects.get(id=id)
class Query(graphene.ObjectType):
    authors = graphene.List(Author)
    posts = graphene.List(Post)
    def resolve_authors(self, info):
        return AuthorModel.objects.all()

    def resolve_posts(self, info):
        return PostModel.objects.all()
schema = graphene.Schema(query=Query)

Now you can run the server and go to localhost:8000/graphql to test out some GraphQL queries like this one:

query {
  authors {
    name
      posts {
        title
      }
  }
}

The most important thing to remember is that you can query any fields you want, which will affect the overall load time and traffic usage on the UI side.

For larger user bases, it’s important to keep traffic low and only query the fields you need. In the case of REST API, you will get all fields anyway.


More great articles from LogRocket:


query {
  posts {
    title
    author {
      name
    }
  }
}

This is the basic query outcome from the Python definition. It’s pretty simple and, compared to REST APIs, more expressive than you may think. You can find the final code for this exercise here for reference.

What about GraphQL Subscriptions?

GraphQL Subscriptions function as a way to tell the server to retrieve data based on a specific query whenever the data is available.

It all works with WebSockets in near real time, which means we have to somehow include Django Websockets and configure our backend server for accepting WebSockets.

Basically, GraphQL is just an API query language interpretation that works with any kind of network transportation when handling client and server-side GraphQL language interpretation.

It may seem difficult at first, but there’s an open source library and Django GraphQL Subscriptions over at the Django WebSockets module.

# settings.py

GRAPHENE = {
    'SCHEMA_INDENT': 4,
    'MIDDLEWARE': [
        # Other middlewares

        'graphenedjangosubscriptions.depromise_subscription',
    ]
}

This will be enough to handle the subscription schema later on as a Subscription query.

As a quick aside, Pinterest actually works entirely on GraphQL Subscriptions, which is all built on top of Django Backend (but probably modified quite a bit).

Conclusion

In my opinion, Django with GraphQL is more powerful and extensible than Django with REST API.

However, it isn’t battle tested and large companies are still in the process of adopting this kind of combination. Still, based on what you can get out of this simple configuration, imagine how much more comfortable web development will be when you use Django with GraphQL with modern technologies.

Monitor failed and slow GraphQL requests in production

While GraphQL has some features for debugging requests and responses, making sure GraphQL reliably serves resources to your production app is where things get tougher. If you’re interested in ensuring network requests to the backend or third party services are successful, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
Tigran Bayburtsyan Cofounder and CTO at Hexact, Inc. Software scalability expert!

3 Replies to “Django and GraphQL: Demo project with Graphene”

  1. Any and all graphQL servers can be introspected with GraphiQL. Dev mode has nothing to do with it. The spec itself specifies that.

  2. Under “setting up models” and “…graphene” sections above…

    There are a couple code examples with indentation issues, publishing issues?
    Just noting that ‘cut n paste’ will not work from those sections.

    1. Thanks for the catch, that should be fixed now. There’s also a link to the GitHub repo for further reference.

Leave a Reply