Django, GraphQL and Vuejs

by
15th April 2019

In this post we are going to review an already built project that runs a GraphQL API service using Django/Django Graphene and a Vuejs frontend as a client. Using the Vuejs app, users will be able to authenticate against the backend sending a JSON Web  Token sent in a HttpOnly Cookie (because we already know that local storage or session storage are bad options to save sensitive data). The idea is to review something working and to have it as a reference/example for your future projects.

About the tools we are going to use

Lets list the libraries we are going to use:

Building the project

In order to keep this post shorten, instead of describing step by step how to configure the backend and frontend, we are going to use an already configured project and then highlight the important files/configurations. To build the project you need to have installed and running Docker and Docker Compose.

So, lets start by cloning the repo:

git clone https://github.com/devsar/django-graphene-vuejs.git

Change directory to django-graphene-vuejs and excecute the autoinstall.sh script:

cd django-graphene-vuejs && ./autoinstall.sh

You will end up with Django running on port 8000 and the Vuejs on port 8080.

Now, lets run (in another terminal, in the same path where docker-compose.yml exists) the migration scripts with:

docker-compose run backend migrate

And finally, lets create a super user with:

docker-compose run backend django-admin createsuperuser

Thats all! (you will use the created user above, later in the frontend)

About the Backend

Its a common Django project (created with django-admin startproject) which has the following deps installed:

All the backend requirements are described in the Pipfile , so if you want to install it locally be sure to have pipenv on your system and excecute: pipenv install.

File backend/settings.py

Lets take a look at the settings.py file. You will find graphene_django listed on INSTALLED_APPS and a GRAPHENE dict which describes where the project main schema is located (in this example is at backend.schema.schema).

Also, on settings.py we make use of graphql_jwt.middleware.JSONWebTokenMiddlewaremiddeware and graphql_jwt.backends.JSONWebTokenBackend authentication backend. This will let us use JSON Web Token authentication for Django GraphQL .

File backend/schema.py

The schema is the place where we describe our collection of types (and its fields) . If its your first time with GraphQL, you can read more about Schemas and Types here. You will see that backend.schema.schema is like the main schema from the project (similar to the main urls.py) which imports other schemas defined in other apps. You can see another schema example in the users app.

File backend/urls.py

The important line:

path('graphql/', csrf_exempt(jwt_cookie(GraphQLView.as_view(graphiql=True))))

Here we defined an endpoint graphql/which will receive the frontend requests. This endpoint is served by the GraphQLView (works as a common Django Class Based View) which is decorated by the jwt_cookie decorator.

The jwt_cookie decorator will set in the django response a httpOnly cookie with the JWT which then (when the request comes back) will be used by the graphql_jwt.backends.JSONWebTokenBackend authentication backend to authenticate users.

GraphiQL is a web interface that lets you write and send graphql queries. Its very useful while you are programming (but remember to disable it on prod).

Questions about the Backend?

If you have some doubts/questions about the previous steps, i recommend you to follow this tutorial. It will guide you step by step on how to build a clone of Hackernews , implementing a GraphQL API using Django.

Lets go with the Frontend

At src/frontend you will find a basic vuejs project (created with vue create frontend) already configured to send requests to the backend /graphql endpoint. Its important to mention that in order to be able to query the graphql service, we need a graphql client. In this example, the project is using Apollo Boost as a client, and just for reference, if you need to install it locally on your frontend projects, you can do it with the command:

npm i --save apollo-boost apollo-cache-inmemory apollo-client apollo-link-http graphql graphql-tag vue-apollo

File frontend/src/main.js

In this file, where the Vue app is created, you will find the Apollo Client being configured. Apollo client has a lot of configuration options, but the basic ones are:

  • Create a Link (use createHttpLink from apollo-link-http). Here set the uri where the graphql backend is running (in this example: http://localhost:8000/graphql/ and set credentials: include to make the browser send the JWT cookie on each request. Important: The docs will tell you to use new HttpLink but thats wrong, if you want to know why, here is the pull request to fix it.
  • Create a Cache (InMemoryCache from apollo-cache-inmemory)
  • Create an apolloProvider with VueApollo using the cache and link created above
  • Use the apolloProvider in your Vue app.

Later, in your components, you will be able to access the apollo client with this.$apollo (send queries with this.$apollo.query(...) or mutations with this.$apollo.mutate(...))

File frontend/src/App.vue

In this file you will see a simple login form asking for a username and password (its a simple toy example). There are two buttons:

  • Login. When clicked, it’ll excecute the login method. This will sends a mutation that will return a JWT token.
  • Update user info: Its a form that will send mutations to update user data (first name, last name and email).

Something to pay attention is at line 82, the apollo section. The me query will fetch the user first name, last name, id and email. The interesting part is that when the updateUser method gets excecuted and the mutation is sent, apollo client will realize (by the user id) that you are updating an user you requested info before (me query), so it’ll automatically update the user data (first name, last name and email). You can read more about this behavior on this blog post.