django-rest-graphql

Django API : Create REST API and GraphQL with MySQL

By Rasyue | On December 14, 2020

In this tutorial we will be using Django that serves as our backend application and create both REST API and GraphQL with MySQL for the database.

django rest api graphql rasyue

Introduction

Django is a Python framework that is open-source and follows the model-template-views architectural pattern. If you have used a framework the follows the model-template-views before, picking up Django will be much more easier.

To follow along with this tutorial, make sure you have these installed:

  1. Python
  2. MySQL (I am using XAMPP which is easier to setup)

Without further ado, let’s get started.

Django REST API

First, let’s create a folder for our project and then let’s create virtual environment for our project. Open your command prompt and run this. I will be using Anaconda but it’s fine if you installed Python.

mkdir django
cd django
python -m venv venv
venv\Scripts\activate

With that, you will now have activated your virtual environment. Now, let’s installed Django and create our Django app.

pip install django // or you can use python -m pip install Django
django-admin startproject rasyue
cd rasyue
python manage.py runserver

You can replace rasyue with any name that you like. Now you should be able to go to localhost:8000 and see your default Django app.

django rest api graphql rasyue default app

But if you read the command prompt you should be seeing something like this.

django rest api graphql rasyue django-command prompt

Django returned a notice to tell us about the unapplied migration. Let’s talk about migration now.

Migration in Django

First, open up your settings.py file which is under your_project_name/settings.py. Mine will be rasyue/settings.py.

You should see something like this.

Look at the database object/dictioanary. By default, Django will use sqlite that comes along with the Django package.

We are going to change that to use MySQL instead. Now fire up your xampp mysql.

Replace your database object/dictionary with below.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'rasyuedjango',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on
        'PORT': '3306',
    }
}

Remember to create a database for your Django app in MySQL. Mine is rasyuedjango.

And now we need to run the migration. Run the following code in your command prompt.

python manage.py migrate

python manage.py runserver

Take a look in your db and you should see a few tables have been created.

Django API App

At this point, if you are a beginner and has no idea what’s a REST API is, a REST API is the standard way to provide data to another party/app.

For example, let’s say you have a frontend app that you need to display User data, you can consume your backend REST API to fetch that data.

To create a REST API in Django, first we need to run the code below.

pip install djangorestframework

That will install the DRF(django rest framework) that will make our job easier.

REST API Data

A typical REST API should be providing some sort of data, since we do not have any data to provide, let’s create some.

Let’s just assume we want to provide data regarding books.

The steps that we need to do are as follow:

  1. Create a super user for our django app to access the admin page
  2. Secondly, create another app in our django app to handle our REST API.
  3. Thirdly, create app model.
  4. Next, create a serializer.
  5. Then, create views and urls.
  6. After that, create some data for our books data.
  7. Finally, we need to test our REST API.

With all the steps listed, let’s get to work.

Creating Super User

To create a super user, first we need to start our app and run the following command.

python manage.py createsuperuser

The command will ask for username, email and password. Enter it and then go to localhost:8000/admin. A login box will appear, go ahead and login with the username and password that you entered previously.

rasyue-django-admin-login-box

Upon successful login, you will see this page.

admin page django

Now that we can log into the admin page. We need to create another app in our Django project.

Books App

First run the following command.

python manage.py startapp books

This command will create another app in your Django project.

django startapp

Notice that in our project directory, another folder called Books has been created and it consists of several files like models.py, admin.py, views.py and so on.

Apps In Django

Before we go further, a couple of things you need to understand is:

  1. Although, the command python manage.py startapp books create another app in our Django project, it is not a separate Django app. In Django, you can create several separate apps with each having unique functionality. If you have use Angular or React before, you can treat app like a component.
  2. Each of the app that you created are not linked to the core project by default, you will have to tell Django about the apps that you created which I will show later.

Registering Created App (Books)

Open up your settings.py and paste the following.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books',
]

It should look like this.

django settings

With that, we have successfully registered our books app.

Creating Model

In books/models.py, paste the following.

class Book(models.Model):
    title       = models.TextField()
    description = models.TextField()
    price       = models.TextField()
     def __str__(self):
        return self.title

    class Meta:
        ordering = ('title',)

Open your books/admin.py and paste the following.

from django.contrib import admin
from .models import Book

# Register your models here.

admin.site.register(Book)

Now run the command.

python manage.py makemigrations
python manage.py migrate

start you server and go to admin page
python manage.py runserver

With that, when you go to the admin page. You should see something like this.

django admin books

If you click on the Books, you can create a new book record, so go ahead and create as many as you like as these data will later be used in the REST API.

Creating Serializers

Create a new file and name it serializers.py in the book folder. It should be books/serializers.py. In the file, paste the followings.

from rest_framework import serializers

from .models import Book

class BookSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Book
        fields = ('title', 'description')

Next, create another file and name it urls.py, paste the following.

from django.urls import path
from django.conf.urls import include
from rest_framework import routers
from . import views

router = routers.DefaultRouter()
router.register(r'books', views.BookView)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

Open your views.py and paste the following.

from django.shortcuts import render

# Create your views here.
# views.py
from rest_framework import viewsets

from .serializers import BookSerializer
from .models import Book


class BookView(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = Book

Lastly, open your project root urls.py or rasyue/urls.py and paste the following. We need to register the books/urls.py in our root url.

"""mysite URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from books import views
from django.conf.urls import include

urlpatterns = [    
    path('admin/', admin.site.urls),
    path('books-api', include('books.urls')),
]

Also, in your settings.py, include rest_framework.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books',
    'rest_framework',
]

Now, start your app and go to localhost:8000/books-api

Play around with the REST API and understand it more. We are going to move on to create GraphQL.

Django API GraphQL

So now, lets begin to create our GraphQL by first running below command.

pip install django-graphene

Now, in the REST API above, we need to create the serializers but for graphql, we will have to create the schema.

Go ahead and create two file name schema.py, one for books/ and another one for rasyue/.

It should look like this.

rasyue schema

Open the books/schema.py and paste the following.

import graphene
from graphene_django.types import DjangoObjectType, ObjectType
from .models import Book

class BookType(DjangoObjectType):
    class Meta:
        model = Book

class Query(ObjectType):
    book = graphene.Field(BookType, id=graphene.Int())
    books = graphene.List(BookType)
    

    def resolve_book(self, info, **kwargs):
        id = kwargs.get('id')

        if id is not None:
            return Book.objects.get(pk=id)

        return None

    def resolve_books(self, info, **kwargs):
        return Book.objects.all()


class BookInput(graphene.InputObjectType):
    id = graphene.ID()
    title = graphene.String()
    description = graphene.String()
    price = graphene.String()
   

class CreateBook(graphene.Mutation):
    class Arguments:
        input = BookInput(required=True)

    ok = graphene.Boolean()
    book = graphene.Field(BookType)

    @staticmethod
    def mutate(root, info, input=None):
        ok = True
        book_ins = Book(title=input.title)
        book_ins.save()
        return CreateBook(ok=ok, book=book_ins)


class UpdateBook(graphene.Mutation):
    class Arguments:
        id = graphene.Int(required=True)
        input = BookInput(required=True)

    ok = graphene.Boolean()
    book = graphene.Field(BookType)

    @staticmethod
    def mutate(root, info, id, input=None):
        ok = False
        book_ins = Book.objects.get(pk=id)
        if book_ins:
            ok = True
            book_ins.title = input.title
            book_ins.save()
            return UpdateBook(ok=ok, book=book_ins)
        return UpdateBook(ok=ok, book=None)

class Mutation(graphene.ObjectType):
    create_book = CreateBook.Field()
    update_book = UpdateBook.Field()



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

To explain the above code, in GraphQL we have two basic operations which are Query and Mutation. While Query is for fetching data, Mutation is used to update or create.

We created BookType to be used in Query operation which is fairly easy to understand.

We also created BookInput which is used to tell GraphQL the type of data that should be used in UpdateBook and CreateBook.

Now open your rasyue/schema.py and paste the following.

import graphene
import books.schema

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

class Mutation(books.schema.Mutation, graphene.ObjectType):
    pass

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

Now, open your rasyue/urls.py and paste the following.

"""mysite URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from books import views
from django.conf.urls import include
from graphene_django.views import GraphQLView
from .schema import schema

urlpatterns = [    
    path('admin/', admin.site.urls),
    path('books-api/', include('books.urls')),
    path('graphql/', GraphQLView.as_view(graphiql=True)),
]

Lastly, open your rasyue/settings.py and modified it like so.

INSTALLED_APPS = [
    'graphene_django',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books',
    'rest_framework',
]

GRAPHENE = {
    'SCHEMA': 'rasyue.schema.schema'
}

Your settings.py should look like this.

And that’s it. Run your django project and go to localhost:8000/graphql

The End..

And with that, this is the end for this tutorial. Hope if helps you. Thank you and stay tuned.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*
*