Graphql in django using Graphene-Django

GraphQL is a powerful query language for APIs that gives clients exactly the data they need, and Django is a robust web framework for building scalable web applications. In this guide, we'll explore how to integrate GraphQL into a Django project using Graphene-Django library, allowing us to build flexible, efficient APIs with less overhead and greater control over data fetching.

Before starting this guide, it is highly recommended to read this guide: GraphQL in Python using Graphene

In this guide, I assume that you are familiar with basics of Django.

Open terminal or command prompt based on your OS and create a working directory and go inside the directory

mkdir graphql_with_django
cd graphql_with_django


Create a virtual environment and activate it.

python -m venv .venv
source .venv/bin/activate # for linux/macos
.venv\Scripts\activate # for windows


We will install django and graphene-django . Open your terminal/command prompt and

pip install django
pip install graphene-django


Now, we create our django project and also create an app named course.

django-admin startproject core . # create project inside current directory
django-admin startapp course


Now, lets add graphene_django and course to INSTALLED_APPS in settings.py file of django project.

INSTALLED_APPS = [
    ...
    "graphene_django",
    "course",
]


Now, lets add URL for graphql in core/urls.py

# urls.py

from django.urls import path
from django.views.decorators.csrf import csrf_exempt

from graphene_django.views import GraphQLView

urlpatterns = [
    # ...
    path("graphql/", csrf_exempt(GraphQLView.as_view(graphiql=True))),
]
  • We use csrf_exempt decorator to make sure that CSRF protection enabled in Django application doesn't block our API clients from creating POST request to graphql endpoint. However, this approach is not recommended for production environments, as it disables an important security mechanism that helps prevent Cross-Site Request Forgery(CSRF) attacks.
  • GraphQLView is a class-based view from Graphene-Django, used to handle GraphQL queries.
  • graphiql=True enables the GraphiQL UI — a browser-based IDE where you can write and test GraphQL queries interactively.

Now, create schema.py file inside core folder and create schema in core/schema.py

import graphene


class Query(graphene.ObjectType):
    pass

class Mutation(graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query, mutation=Mutation)

If this schema variable confuses you, explore one of these links:
GraphQL in Python using Graphene
Building a GraphQL API in Python with PostgreSQL Integration

Now, add schema to core/settings.py.

# ...
GRAPHENE = {
    "SCHEMA": "core.schema.schema",
}


Lets create Course model in our course/models.py.

from django.db import models


class Course(models.Model):
    title = models.CharField(max_length=100, blank=False, unique=True)
    description = models.TextField()
    language = models.CharField(max_length=20, default="English", blank=True)
    price = models.PositiveIntegerField()
    currency = models.CharField(max_length=10)


    def __str__(self):
        return str(self.title)


Migrate the database changes and register this Course model to admin by editing course/admin.py file.

from django.contrib import admin

from course.models import Course

admin.site.register([Course])

Create a superuser to login to admin panel and add some data to Course model.

Now, let's add queries to course/schema.py file to get course lists and course by id.

import graphene
from graphene_django import DjangoObjectType


from .models import Course


class CourseType(DjangoObjectType):
    class Meta:
        model = Course
        exclude = ()


class Query(graphene.ObjectType):
    courses = graphene.List(CourseType)
    course_by_id = graphene.Field(CourseType, id=graphene.Int()) # arugment must be declared here 

    def resolve_courses(self, info):
        return Course.objects.all()

    def resolve_course_by_id(self, info, id):
        try:
            course = Course.objects.get(id=id)
            return course 

        except Exception as e:
            return Exception(f"Error: {str(e)}")
  • We create CourseType, inheriting from DjangoObjectType. This will create a Type based on model Course.
  • exclude tells Django which fields to leave out when generating the type. Alternatively, we can add fields, to include fields that we want in our type. For eg: fields = ["title", "price"]
  • resolve_courses(), gives us list of all courses
  • resolve_course_by_id(), gives us course information based on id provided with query request.

Now, lets add Mutation to course/schema.py.

#...

class CreateCourse(graphene.Mutation):
    class Arguments:
        title = graphene.String(required=True)
        description = graphene.String()
        language = graphene.String(default_value="English")
        price = graphene.Int()
        currency = graphene.String(default_value="NPR")

    ok = graphene.Boolean()
    course = graphene.Field(CourseType)

    def mutate(self, info, title, description, language, price, currency):
        try: 
            course = Course.objects.create(
                title=title,
                description=description,
                language=language,
                price=price,
                currency=currency
            )
            return CreateCourse(course=course, ok=True)
        except Exception:
            return CreateCourse(course=None, ok=False)

class Mutation(graphene.ObjectType):
    create_course = CreateCourse.Field()
  • Here, we create CreateCourse class that has mutate() method to handle creation of Course object. This mutation returns two main fields:

    • ok: A boolean value that simply tells us whether the course was created successfully or not.

    • course: The newly created course object, containing all the relevant course details like title, description, language, and price.

    These fields help the client know if the operation worked and, if it did, access the newly created course data immediately.

  • Also, we create Mutation class that contains field to handle various mutations. In our case, we have only one field, create_course.

Now, we will extend Query and Mutation on core/schema.py from Query and Mutation from course/schema.py

# ...
import course.schema

class Query(course.schema.Query, graphene.ObjectType):
    pass

class Mutation(course.schema.Mutation, graphene.ObjectType):
    pass
# ...


With the queries and mutations ready, it’s time to test them out right in the browser. Open your favorite browser and open http://localhost:8000/graphql. Make sure you have started your django web application.

query allCourses{
  courses{
    id
    title
    description
    price
    currency
    language
  }
}


mutation courseCreator{
  createCourse(
    title:"How to install Flask on your machine",
    description: "A course on installing Flask on your machine",
    language:"English",
    price: 200
  )
  {
    ok
    course{
      id
      title
      description
      price
      currency
      language
    }
  }
}


You can find code for this guide on rasbin111/tutorials.

To explore more about graphene_django, you can visit documentation: Graphene-Django.