How we send data from Django to Gatsby.js through GraphQL (part one)

Igor Strapko
Good Praxis
Published in
4 min readJul 27, 2022
The GraphQL logotype on the yellow background

Recently my work colleague Baron and I had the pleasure to build some web infrastructure for a really interesting project. The goal was to build a custom headless CMS which could collect data records and then send them in GraphQL format to the front-end application based on Gatsby.js framework.

We decided to create our back-end with Django; it has an amazing and well customizable CMS side, which probably is one of the main reasons why so many Python developers choose it so often.

The only problem is that, other than Gatsby itself, Django does not have a built-in GraphQL’s layer. Luckily there’s graphene-django — a third-party library, which, installed on the top of Django, gives us an opportunity to use GraphQL in our project.

So just after setting up a virtual environment (I use virtualenvwrapper, but you can use your favourite tool to create it) then running command

pip install django

inside our brand new virtual environment, we created our Django project:

mkdir our_project
cd our_project
mkvirtualenv dgg
(dgg) pip install django
(dgg) django-admin startproject our_project_name .

(As you may know, adding a period right after the name of your project lets you create it directly in the current directory and therefore avoid creating another folder for it, making the whole structure a bit less complicated. But it’s not necessary so you can run the command without the dot too.)

After this step it’s worth doing the initial migration to build Django basic database structure:

(dgg) python manage.py migrate

Then we need to create a superuser a.k.a. admin, using the command

python manage.py createsuperuser

Django will ask you here about your username, email address to be used in case of anything important to tackle against your admin duties, and chosen password.

Before we can start playing with GraphQL, we need to create a new app inside our project and then design some data models, so we can cook something to feed the GraphQL schema. To create a new app just run

(dgg) python manage.py startapp our_app_name

After this, open our_app_name folder and find the models.py file, where you need to add your models. In our last project we created a kind of art exhibition with different visual and sound objects. Our models for this look similar to these ones:

from django.db import models
from django.utils import timezone
class Author(models.Model): name = models.CharField(max_length=100)
bio = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class Artwork(models.Model): STATUS_CHOICES = (
(‘draft’, ‘Draft’),
(‘published’, ‘Published’),
)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=250, unique_for_date=’publish’)
description = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to=’images/’, blank=True, null=True)
video = models.CharField(max_length=200, blank=True, null=True)
audio = models.CharField(max_length=200, blank=True, null=True)
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=’draft’)
def __str__(self):
return self.title

As you can see, we decided to use third party platforms to collect video and audio files, and just pass their URLs into our database fields, we will just collect all image files inside folder images/, which we need to add in our root folder and register it inside our_project_name/settings.py file:

import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / ‘subdir’.BASE_DIR = Path(__file__).resolve().parent.parent[. . .]MEDIA_URL = ‘/images/’MEDIA_ROOT = os.path.join(BASE_DIR, ‘images’)

Do not forget to let Django know about changes in our_app_name/models.py:

python manage.py makemigrations
python manage.py migrate

Also remember to register our new app inside the INSTALLED_APPS list in our_projest_name/settings.py:

INSTALLED_APPS = [
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
‘our_app_name.apps.OurAppNameConfig’,
]

With all of this above sorted we are ready to install the graphene-django layer:

(dgg) pip install graphene-django

And then register it in the same place of our_projest_name/settings.py file like before:

INSTALLED_APPS = [   [. . .]   ‘django.contrib.staticfiles’,
‘our_app_name.apps.OurAppNameConfig’,
‘graphene_django’,
]

It seems like we have got everything now to write schema for GraphQL queries. In our_project_name create schema.py file and type these lines:

import graphenefrom graphene_django import DjangoObjectTypefrom our_app_name.models import Author, Artworkclass AuthorType(DjangoObjectType):
class Meta:
model = Author
fields = (“id”, “name”, “bio”)

class ArtworkType(DjangoObjectType):
class Meta:
model = Artwork
fields = (
“id”,
“author”,
“slug”,
“title”,
“description”,
“image”,
“video”,
“audio”,
“publish”,
“created”,
“updated”,
“status”,
)

class Query(graphene.ObjectType):
all_authors = graphene.List(AuthorType)
all_artworks = graphene.List(ArtworkType)
author_by_name = graphene.Field(
AuthorType, name=graphene.String(required=True))
artwork_by_title = graphene.Field(
ArtworkType, title=graphene.String(required=True))
artwork_by_slug = graphene.Field(
ArtworkType, slug=graphene.String(required=True))
def resolve_all_authors(root, info):
return Author.objects.all()
def resolve_author_by_name(root, info, name): try:
return Author.objects.get(name=name)
except Author.DoesNotExist:
return None
def resolve_all_artworks(root, info):
return Artwork.objects.all()
def resolve_artwork_by_title(root, info, title): try:
return Artwork.objects.get(title=title)
except Artwork.DoesNotExist:
return None
schema = graphene.Schema(query=Query)

In the next step let’s add a few lines inside our_project_name/urls.py file:

from graphene_django.views import GraphQLViewfrom our_project_name.schema import schemaurlpatterns = [
[. . .]
path(‘graphql’, csrf_exempt(GraphQLView.as_view(graphiql=True, schema=schema))),
]

Finally we need to register our schema in our_project_name/settings.py:

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

At this point the back-end part of our project is ready and we can test it by running the server:

python manage.py runserver 8080

We can then type localhost:8080/admin in our browser. After login as admin of our project we can add some Authors and Artworks, and then open localhost:8080/graphql. If we sorted stuff in the proper way we should be able to write queries and instantly check results taken from our database.

That’s it about the back-end part of our project. Stay tuned for Part 2, where we explain how to consume this data in Gatsby.

--

--