What is GraphQL?
Technology is evolving so fast. Every day, old technologies are being replaced by new ones. For many years, REST architecture was dominating web services and APIS. In 2012, Facebook developed GraphQL and open-sourced it in 2015. Since then, it is becoming so popular in the development world. GraphQL is a declarative, strongly typed, data-driven query language to build APIs.
With GraphQL, you can ask exactly what you need from the server with a single API endpoint. Moreover, It aggregates data from multiple related tables and sources going as much deep as needed. In addition, with a strong type checking mechanism, GraphQL helps developers to write more reliable, robust and bug-free codes.
…
Why GraphQL?
Why we should care about GraphQL? Here are some most important reasons to use GraphQL.
- Single API: solution for everything. No need to manage a lot of APIs.
- Strongly-Typed well-defined schema. No more API documentation.
- Get exactly what you need. No more over-fetching and under-fetching.
- Minimum network roundtrips. No more bandwidth wasting.
- Language agnostic next-generation API tool. Very rich and fast-growing community.
…
REST vs GraphQL
Every technology has some pros and cons. RESTful architecture is still very matured and widely used. Where Graphql is growing rapidly and gaining ground over the REST quickly. Here we are covering a quick comparison of GraphQL and REST.
GraphQL | REST | |
Self Documenting | Yes | No |
Learning curve | Difficult | Moderate |
Web caching | No. libraries built on it have caching support | Yes |
Performance | Fast | Round-trip requests take up more time. |
Development Speed | Rapid | Slower |
Data Fetching | Exactly what needed | Over fetching / Under fetching |
…
Graphql with Python/Django
GraphQL is a language-agnostic API tool. Therefore, we can use it with any existing language like Python, Java, PHP, Go, Ruby etc. To use GraphQL with python we will use the Graphene-Python library. It can be easily integrated with Django. Graphene offers easy integration with another open-source library called Graphene-Django. So, we are using Graphene and Graphene-Django to implement GraphQL in this project.
…
1. Setup Django project
We will create a simple blog with very basic functionality. Let’s create the following –
- A project directory called
gqlblog
- A Django project called
morning_blog
- An app within
morning_blog
namedblog
# create the project directory mkdir gqlblog cd gqlblog
Create a virtual environment called blog_env
and activate it.
python3 -m venv morning_env source ./morning_env/bin/activate # on windows morning_env\Scripts\activate
The virtual environment is ready to use. Let’s install Django and configure it. We will use pip
to install python packages.
pip install Django pip install graphene_django
Now create the Django project and app.
django-admin.py startproject morning_blog cd morning_blog # change the directory # Create the app django-admin.py startapp blog
Now Just sync the database.
python manage.py migrate
Let’s run the server.
python manage.py runserver
Copy this URL to your browser.
http://127.0.0.1:8000/
You should see the congratulations message.

Awesome. Everything looks ok. Open the project with your preferred IDE. We are using visual studio code. Go to morning_blog/settings.py
and add blog
app to INSTALLED_APPS
as following.
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog', ]
Within the blog
app, go to models.py
file and create some simple models.
from django.db import models class Author(models.Model): name = models.CharField(max_length=250) description = models.TextField() class Blog(models.Model): title = models.CharField(max_length=300) author = models.ForeignKey(Author, on_delete=models.CASCADE) body = models.TextField()
Now run these commands to create the migrations.
python manage.py makemigrations python manage.py migrate
Let’s create some test data and load it to the database. Create a directory called fixtures
within blog
app. Create a file inside it called blogs.json
and copy the following data.
[ { "model": "blog.Author", "pk": 1, "fields": { "name": "Guido van Rossum", "description": "Python Creator" } }, { "model": "blog.Author", "pk": 2, "fields": { "name": "Ijharul Islam", "description": "Full stack developer." } }, { "model": "blog.Blog", "pk": 1, "fields": { "author_id": 2, "title": "How to build graphql API with Django", "body": "Lorem ipsum is placeholder text commonly used in the graphic, print." } }, { "model": "blog.Blog", "pk": 2, "fields": { "author_id": 2, "title": "Graphql Data validation in Django", "body": "Lorem ipsum is placeholder text commonly used in the graphic, print." } } ]
And run the following command
python manage.py loaddata blogs
You should see the following output in the terminal.
Installed 4 object(s) from 1 fixture(s)
2. Basic Setup for GraphQL with Django
Add graphene_django
to the INSTALLED_APPS
in the morning_blog/settings.py
file:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # Third party apps 'graphene_django', # Custom apps 'blog', ]
Now we need to add an API for graphql
. Let’s update the urls.py
in morning_blog
directory.
from django.contrib import admin from django.urls import path from graphene_django.views import GraphQLView urlpatterns = [ path('admin/', admin.site.urls), path('graphql', GraphQLView.as_view(graphiql=True)), ]
And create another file within morning_blog
directory called schema.py
and add the following code.
import graphene class Query(): pass class Mutation(): pass schema = graphene.Schema(query=Query, mutation=Mutation)
Finally, go to the settings.py
file and add the location of the schema.
GRAPHENE = { "SCHEMA": "morning_blog.schema.schema" }
3. Writing Schema with Graphene
Before writing schema, create a directory within blog
app called schema.py
and add following files.
- Create a file called
authors.py
- Create another file called
blogs.py
So, your final folder structure should like the following.

Let’s add some schema for authors and blogs. Add the following code to the authors.py
file.
import graphene from graphene_django.types import DjangoObjectType, ObjectType from ..models import Author class AuthorFields(): name = graphene.String() description = graphene.String() class AuthorType(DjangoObjectType, AuthorFields): class Meta: model = Author id = graphene.ID(required=True) class AuthorInputType(graphene.InputObjectType, AuthorFields): id = graphene.ID() class DeleteAuthorInputType(graphene.InputObjectType): id = graphene.ID(required=True)
And add the following schema to blogs.py
file.
import graphene from graphene_django.types import DjangoObjectType, ObjectType from ..models import Blog from .authors import AuthorType class BlogFields(): title = graphene.String() body = graphene.String() class BlogType(DjangoObjectType, BlogFields): class Meta: model = Blog id = graphene.ID(required=True) author = AuthorType() class BlogInputType(graphene.InputObjectType, BlogFields): id = graphene.ID() author_id = graphene.ID() class DeleteBlogInputType(graphene.InputObjectType): id = graphene.ID(required=True)
4. Writing Queries
Here we will add some queries for the Author model. Add the following code to authors.py
file.
class Query(ObjectType): author = graphene.Field(AuthorType, id=graphene.ID(required=True)) authors = graphene.List(AuthorType) def resolve_author(self, info, **kwargs): id = kwargs.get("id") return Author.objects.get(id=id) def resolve_authors(self, info, **kwargs): return Author.objects.all()
Also, add some queries for Blog
model. Add the following code to blogs.py
file.
class Query(ObjectType): blog = graphene.Field(BlogType, id=graphene.ID(required=True)) blogs = graphene.List(BlogType) def resolve_blog(self, info, **kwargs): id = kwargs.get("id") return Blog.objects.get(id=id) def resolve_blogs(self, info, **kwargs): return Blog.objects.all()
5. Creating Mutations
To perform Create/Update/Delete operations, we have to add mutations. Add the following mutations to authors.py
file.
class CreateAuthor(graphene.Mutation): class Arguments: input = AuthorInputType(required=True) ok = graphene.Boolean() author = graphene.Field(AuthorType) @staticmethod def mutate(root, info, input): author = Author() for key, val in input.items(): setattr(author, key, val) author.save() return CreateAuthor(ok=True, author=author) class UpdateAuthor(graphene.Mutation): class Arguments: input = AuthorInputType(required=True) ok = graphene.Boolean() author = graphene.Field(AuthorType) @staticmethod def mutate(root, info, input): id = input.get("id") author = Author.objects.get(id=id) for key, val in input.items(): setattr(author, key, val) author.save() return CreateAuthor(ok=True, author=author) class DeleteAuthor(graphene.Mutation): class Arguments: input = DeleteAuthorInputType() ok = graphene.Boolean() @staticmethod def mutate(root, info, input): id = input.get("id") author = Author.objects.get(id=id) author.delete() return DeleteAuthor(ok=True)
Finally, add those mutations to Mutation
class and register it to a schema.
class Mutation(graphene.ObjectType): create_author = CreateAuthor.Field() update_author = UpdateAuthor.Field() delete_author = DeleteAuthor.Field() schema = graphene.Schema(query=Query, mutation=Mutation)
To create, update and delete the Blog, add the following code to blogs.py
file. We are registering our mutations to a schema at the end.
class CreateBlog(graphene.Mutation): class Arguments: input = BlogInputType(required=True) ok = graphene.Boolean() blog = graphene.Field(BlogType) @staticmethod def mutate(root, info, input): blog = Blog() for key, val in input.items(): setattr(blog, key, val) blog.save() return CreateBlog(ok=True, blog=blog) class UpdateBlog(graphene.Mutation): class Arguments: input = BlogInputType(required=True) ok = graphene.Boolean() blog = graphene.Field(BlogType) @staticmethod def mutate(root, info, input): id = input.get("id") blog = Blog.objects.get(id=id) for key, val in input.items(): setattr(blog, key, val) blog.save() return UpdateBlog(ok=True, blog=blog) class DeleteBlog(graphene.Mutation): class Arguments: input = DeleteBlogInputType(required=True) ok = graphene.Boolean() @staticmethod def mutate(root, info, input): id = input.get("id") blog = Blog.objects.get(id=id) blog.delete() return DeleteBlog(ok=True) class Mutation(graphene.ObjectType): create_blog = CreateBlog.Field() update_blog = UpdateBlog.Field() delete_blog = DeleteBlog.Field() schema = graphene.Schema(query=Query, mutation=Mutation)
6. Register the schema to the project.
Now we have to update our root schema file. Go to morning_blog/schema.py
and update it as bellow.
import graphene from blog.schema.authors import schema as author_schema from blog.schema.blogs import schema as blog_schema class Query(author_schema.Query, blog_schema.Query): pass class Mutation(author_schema.Mutation, blog_schema.Mutation): pass schema = graphene.Schema(query=Query, mutation=Mutation)
We are done. It’s time to test our API.
7. Testing the GraphQL API
To test the API, copy this URL to your browser.
http://127.0.0.1:8000/graphql
Test Queries
Copy the following code to graphiql
console and run it.
query { blogs{ id title author { id name } } }
You should see the following outputs.

To get a single blog, write the following query with a specific id.
query{ blog(id: 1){ id title author { id name } } }
You will see the following result.

Test Mutations
Let’s create a blog item with the author.
mutation createBlog { createBlog(input: { title: "How to build GraphQL API with Django.", authorId: 1, body: "GraphQL is a declarative, strongly typed, data-driven query language to build APIs." }) { ok blog { id title author { id name } body } } }
You should see the following result.

Let’s update the previous blog title.
mutation updateBlog { updateBlog (input: { id: 4, title: "How to build GraphQL API with Django - 7 steps.", authorId: 1, body: "GraphQL is a declarative, strongly typed, data-driven query language to build APIs." }) { ok blog { id title author { id name } body } } }
We just updated the title. Check out the updated result.

Awesome. We did lot of things. One thing is left. Let’s delete a blog item.
mutation deleteBlog { deleteBlog (input: { id: 4 }) { ok } }
You will see the following output.

Conclusion
We created a simple Django blog with Graphene and Django-graphene. To use GraphQL, we designed API schema, queries, and mutations. In the end, we tested the CRUD functionality with GrpahiQL console.
Here is the source code of the complete project. You can check it out from here.
Leave a Reply