Building GraphQL APIs in Django with Graphene
Time to read: 6 minutes
GraphQL is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data. It was developed internally by Facebook in 2012 before being publicly released in 2015. It allows clients to define the structure of the data required, and the same structure of the data is returned from the server, therefore preventing unnecessary data from being returned.
GraphQL has three primary operations: Queries for reading data, Mutations for writing data, and Subscriptions for automatically receiving real-time data updates. A GraphQL server provides clients with a predefined schema – a model of the data that can be requested. The schema serves as common ground between the client and the server.
In this tutorial we will use Graphene, a GraphQL framework for Python, to build a Django API that uses queries and mutations.
Tutorial Requirements
To follow along with this tutorial you should have the following items:
- Python 3.6 or newer.
- Virtualenv, to create a virtual environment for the tutorial project.
- Postman, to send requests to our API.
- A working knowledge of the Django web framework.
Project setup
We will begin by creating a virtual environment and installing necessary Python packages.
Create a folder for our project:
Then create a Python virtual environment and activate it. If you are following this tutorial on Windows:
If you are using a Mac OS or Unix computer:
Install the dependencies required for our project:
Create a new django project:
Change your current directory to the project:
Create a api
app in the books_api
project
Next register the api
app and integrate the graphene-django
third-party app we installed earlier into our books_api
project. Find the INSTALLED_APPS
list In books_api/settings.py
and add api
and `graphene-django’ at the end:
While in books_api/settings.py
, go to the bottom of the file and add a GRAPHENE
dictionary with settings for the graphene-django
package:
The SCHEMA
setting tells Graphene where to find the GraphQL schema for the application. We’ll define the schema after we have the database created.
Database model
Open the api/models.py
file and type in the code below to add the Book
database model:
Then create and run the migrations for our database:
To help in testing this project we can now populate our database with some data. To do this, you create a data.json
file in the project directory where the manage.py
file is, and copy the following data into it:
With the data.json
file saved to the current directory, run the command below to import the data into the database:
Next, add the GraphQL endpoint at the end of the urlpatterns
dictionary in file books_api/urls.py
:
Building a Books API with GraphQL
In this section we will be building an API with Graphene using GraphQL queries and mutations.
Implementing a GraphQL Schema
Create a new file in the api/schema.py
folder:
In this step we have created two classes, The first one is BookType
, which adapts the Book
model to a DjangoObjectType
. We set fields
to __all__
to indicate that we want all the fields in the model available in our API.
The Query
class defines the GraphQL queries that the API will provide to clients. The all_books
query will return a list of all the BookType
instances, while the book
query will return one BookType
instance, given by an integer ID. The class defines two methods, which are the query “resolvers”. Every query in the schema maps to a resolver method.
The two query resolvers query the database using the Django model to execute the query and return the results.
Adding data updates with GraphQL mutations
We will now add create, update and delete operations through mutations. While still in the api/schema.py
file, add the code below at the bottom:
The BookInput
class defines fields similar to our Book model object to allow the client to add or change the data through the API. We will use this class as an argument for our mutation classes.
Let’s add a mutation to create new books. Add the following code at the bottom of api/schema.py
:
The CreateBook
class will be used to create and save new Book
entries to the database. For every mutation class we must have an Arguments
inner class and a mutate()
class method.
We defined an instance of the BookInput
class we created earlier as our arguments, and we made it mandatory with the required=True
option. After that we defined the model we are working with by doing this book = graphene.Field(BookType)
.
In the mutate
method we are saving a new book by calling the save()
method on a new Book
instance created from the book_data
values passed as argument.
Below you can see the implementation of the UpdateBook
mutation. Add this code at the bottom of api/schema.py
:
The UpdateBook
mutation class is very similar to CreateBook
. The difference here is the logic in the mutate()
method, which retrieves a particular book object from the database by the book ID
provided and then applies the changes from the input argument to it.
Finally, let’s add a delete mutation. Add the code that follows at the bottom of api/schema.py
:
In the DeleteBook
mutation class we have graphene.ID
as the only argument. The mutate()
method uses this id to remove the referenced book from the database.
We now have two queries and three mutations defined. To register these with Graphene, add the code below at the end of api/schema.py
:
Testing the GraphQL API
We are not ready to test the API. Let’s start the Django server:
Now visit http://127.0.0.1:8000/graphql
in your browser. You should see the GraphIQL interface for interactive testing of the GraphQL API.
The black arrow in the diagram above is where you input your GraphQL code. Then you click on the play button in the top left corner of the screen to run the code and get a result in the area indicated with the blue arrow.
Issuing a query
Queries are used to request data from the server. The GraphQL code below is requesting all the books from the database. Enter it in the left-side panel of the GraphIQL interface.
Press the play button to execute the query and see the results in the right-side panel.
Next try the following query, which requests a single book by its id
:
Note how each query can specify which of the attributes of the book model need to be returned.
Creating a book
The following GraphQL snippet defines a mutation that adds a new book to the database:
Updating an existing book
The next GraphQL mutation updates the book with id=6
:
Deleting a book
The final mutation example deletes the book with id=6
from the database:
Testing the Book API with other GraphQL clients
Django CSRF prevents unauthenticated users on the website from performing malicious attacks. Given this, any POST request made from an external application outside the Django site will result in a 403 Forbidden Error
.
To avoid this there are two options. The most secure option is to add the CSRF token generated by the Django application to the POST
requests that your client makes to the GraphQL endpoint. See the Ajax section in the Django documentation to learn about this option.
An easier, but less secure option is to exempt the GraphQL endpoint from CSRF protection. To do that, open theapi/urls.py
file and change the definition of the GraphQL endpoint as follows:
The csrf_exempt
wrapper added to the GraphQLView
removes the CSRF token verification from the endpoint.
If you want to make sure the CSRF protection does not interfere with your GraphQL endpoint, you can use Postman to send GraphQL requests to the Django API:
Using the above screenshot as a reference, follow these steps to send a GraphQL request with Postman:
- Paste your GraphQL endpoint
http://127.0.0.1:8000/graphql
in the box with the purple arrow. - Click on the first white arrow pointing to the “Body” option
- Click on the GraphQL options at the second white arrow
- Paste your query code in the query box and click on the “Send” blue button.
- You will see the result of your API request at the bottom, in the light green arrow area.
- Notice the blue arrow area, where you should be making a GET request for queries, or a POST request for mutations.
Try the code snippets we used above to test our API through Postman.
Conclusion
In this tutorial we have created a simple GraphQL API in Django using the Graphene-Django package built on top of Graphene, which made it easy to add GraphQL functionality to our Django application.
We created queries to read data, mutations to write and change data and tested our API using the GraphIQL interface provided by the Graphene-Django library and the popular API client Postman. You can find the complete code for the project here.
Adeyemi Atoyegbe is a self-taught Python developer. You can find him on Twitter, GitHub.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.