Django - GraphQL - React Integration Tutorial: Part-2 + Image
Pixly Logo
Django - GraphQL - React Integration Tutorial: Part-2

Django - GraphQL - React Integration Tutorial: Part-2

2019-11-27

Create GraphQL API

In the first part, we created the Django project with item app that includes our movie model. In this part, we will create a simple api with graphql that will response queries that requested from our client-side app.

Here the links of all parts of this tutorial:

 

Step-1: Create API app

Let's create our second app that will be responsible for GraphQL API.

# djr/
# create app with the name gql
# (name is not necessarily to be gql)
python manage.py startapp gql

 

 

Step-2: Configure Url endpoints and necessary settings

Add url endpoint that all the API requests will be done through.

Note: (graphiql=True) option is responsible for interactive GraphQL API browser. We will use it for manually querying the database.

from django.contrib import admin
from django.urls import path
from graphene_django.views import GraphQLView
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import TemplateView

urlpatterns = [
    path('admin/', admin.site.urls),

    # apiclient on client-side will request this adress later
    path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))),

    
    # index.html file will be our root template. When a user opens our webste,
    # this file will be sent by server at first. After then, api requests
    # will directed above address.

    # (it points to ~/Blog/djr/templates/index.html)
    # (currently there is no file, webpack production bundle will come here )
    path("", TemplateView.as_view(template_name="index.html")),
]

 

Define the schema location for Graphene in the settings.py file of your Django project. SCHEMA location points to our schema that we will create in a moment.

# djr/djr/settings.py
GRAPHENE = {
    'SCHEMA': 'gql.schema.schema'
}

 

Create a schema.py file in gql directory.

# djr/gql/schema.py
import graphene

# this is what we define SCHEMA in settings.py
schema = graphene.Schema(query=Query)

 

 

Step-3: Define API model and query

Now, we should clearly define the API requests and its relevant type of data.

First, we will create an API model type and its resolvers that will be the interface of our previously defined movie model.

You can also define custom types with graphene.ObjectType that is not connected to any pre-defined django-model.

 

API-Model

When we create api-model, we first define api-model-fields with respect to our original movie model. There is no obligation to define all the field, but we will do. Also, you can write custom fields that is not defined before.

Let's look at how our movie model fields and api-model fields are paired.

 

Compare your movie mode with API model-type

 

Resolvers

After the fields, we will define resolvers which is responsible for logic part. The second argument of resolvers is info argument which holds useful information like authentication or http information.

 

Queries

Now we are going to write our queries. Client side app will make their requests according to these queries. For the sake of simplicity only two queries will be defined.

The movie_list query returns all the movies in the database.

The movie query returns only specific movie, if slug of the url matches any slug field of a movie.

The final code of schema.py file is here:

 

import graphene
from items.models import Movie
from graphene_django.types import DjangoObjectType

# api-movie-model
class MovieType(DjangoObjectType):
    id = graphene.Int()
    name = graphene.String()
    year = graphene.Int()
    summary = graphene.String()
    poster_url = graphene.String()
    slug = graphene.String()

    class Meta:
        model = Movie

    def resolve_id(self, info):
        return self.id
    
    def resolve_name(self, info):
        return self.name

    def resolve_year(self, info):
        return self.year

    def resolve_summary(self, info):
        return self.summary

    def resolve_poster_url(self, info):
        # Note: in client side app snake_case fields
        # will be resolved as camelCase
        # Eg: poster_url ==> posterUrl
        return self.poster_url

    def resolve_slug(self, info):
        return self.slug


class Query(graphene.ObjectType):
    movie_list = graphene.List(MovieType)
    movie = graphene.Field(MovieType, slug=graphene.String())

    def resolve_movie_list(self, info, *_):
        # for large lists only query what you need
        return Movie.objects.all().only("name", "poster_url", "slug")
    
    def resolve_movie(self, info, slug):
        movie_queryset = Movie.objects.filter(slug=slug)
        if movie_queryset.exists():
            return movie_queryset.first()

schema = graphene.Schema(query=Query)

Writing API for backend is finished. Now, we can check it in the GraphQL interactive browser.

 

 

Step-3: Interactive graphql playground

Please run the server and open http://127.0.0.1:8000/graphql in the browser and write this. You will see the response to this query.

query {
  #the query name
  movieList{
    # the fields which we will request
    id,
    name,
    posterUrl, #camelCase
  }
}

 

Our second query has arguments. We can make the request like this:

query {
  #the query and argument
  movie(slug:"the-matrix-1999"){
      # the fields which we will request
      id,
      name,
      posterUrl, #camelCase

    }
}

 

then the response will be:

{
  "data": {
    "movie": {
      "id": 2571,
      "name": "The Matrix",
      "posterUrl": "<https://image.tmdb.org/t/p/w185/lZpWprJqbIFpEV5uoHfoK0KCnTW.jpg>"
    }
  }
}

We checked that our API is ready.This part of the tutorial is finished. You can stop the server.

 

 

Next, we will create a single page application with React. Then we make requests to our backend.