Build a REST API with Django Rest Framework and MySQL
By: Rashad Russell
Tags: MySQL, Django, API, Django Rest Framework, Python

Django — Python Web Framework

Table of Contents

Introduction

Django is a Python web framework that provides all the tools necessary for building modern web applications. In this tutorial, we are going to learn how to build a basic API that can be used to serve data to any client-side application including websites, mobile apps, desktop apps, and more. We will use the Django Rest Framework library to help us design the API and MySQL as the database.

For our example, we will build a todo list API called TodoAPI. Our API will allow users to perform basic REST actions: create, delete, update, and delete on list items. After this tutorial, you should be equipped with the skills to develop other RESTful CRUD APIs with Django.

Full Code: https://github.com/rashadrussell/beyond-light-creations/tree/master/tutorials/todolist-rest-api

Prerequisites

Below are the primary tools required to build our API. We’re going to assume you already have Virtualenv, MySQL, and Python dependencies installed.

MySQL: v8.0 — https://dev.mysql.com/downloads/mysql/

Python: v3.9 — https://www.python.org/downloads/

Virtualenv: v20.1.0 — https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment

Pip: 20.2.4 — This comes installed with Python 3

Django: v3.1.2 — This will be installed in requirements.txt

Django Rest Framework: v3.12.2 — This will be installed in requirements.txt

Step 1: Setup Django Development Server

Create a virtual environment using Virtualenv. It is a good idea to build Python based projects while in a virtual environment to avoid conflicts amongst the packages being used in your current project and those built in the past, or potentially in the future.

$ python3 -m venv todoapi_env

$ cd todoapi_env

# Activate the virtual environment

$ source bin/activate

Create a directory called todoapi and navigate to it.

$ mkdir todoapi

$ cd todoapi

Next we need to install our application dependencies. Create a file called requirements.txt, which is used to list all of our application dependencies.

todoapi/requirements.txt

Install all application dependencies:

$ pip install -r requirements.txt

Use Django’s admin cli tool to initialize a project:

$ django-admin startproject todoapi

$ cd todoapi

Start the Django server

$ python manage.py runserver

The Django server should be running on port 8000. To verify that the server is running properly, you can visit the Django template site at http://localhost:8000. Ignore the following server warning about migrations for now:

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run ‘python manage.py migrate to apply them.

We will revisit that later when we start working on our models. You should see the following image when you visit http://localhost:8000. Congrats, your Django setup was successful!

Step 2: Setup Django Rest Framework

Now that we have Django’s development server running, it’s a good time to connect Django Rest Framework. Django has a settings file where you can configure any third-party middleware and plugins. Include the following code line at the bottom of the INSTALLED_APPS array in the settings.py file.

todoapi/settings.py

INSTALLED_APPS=[

...,

'rest_framework',

]

Step 3: CORS Headers

We still have more configuration to do in the settings.py file. Since we are building a standalone API server, we need to create a white list of approved web domains that are allowed to retrieve data from our API. This is known as Cross-Origin Resource Sharing (CORS).

For the sake of this tutorial we can allow any outside domain to make requests to our API. Just add the asterisk (*) symbol, which stands for “wild-card”, to the ALLOWED_HOSTS configuration array.

Note, granting all domains access to your API is a security issue in production, so it should only be done in a development environment. In production, you would specify the exact domains you want to grant access such as “www.example.com”.

todoapi/settings.py

...

ALLOWED_HOSTS = [‘*’]

...

Step 4: Create the Todo List App

Django does a good job of guiding developers in building applications with modularity. Django has a concept called “apps”, which we use to logically separate features into stand-alone packages. The reason behind this setup is for these “apps” could be reusable in other projects.

Let’s create the todo list API app:

$ python manage.py startapp todolist

$ cd todolist

Step 5: Models

Models in Django are what allow us to connect to the database. A Django model represents the schema structure behind the database tables. Django’s object relational mapping (ORM) makes it easy for us to perform various queries, which we will use to transform user requests in our Views to read and write operations on the database.

The second major concept with models in Django are model “migrations”. Migrations are operations on the database that transform the schema structure. Whenever you make a change to a model you must manually run a migration to update the database schema. Furthermore, adding middleware to the settings.py file may also require you to run a database migration if that middleware requires data to be stored or schema to be updated.

Previously from Step 1 above, when we setup our Django development server, remember the warning we received that we needed to run a couple migrations. By default, Django has a set of middleware pre-configured to perform schema updates to the database. Before we fix this warning, we need to connect our Django project to a database server.

In this tutorial, our database system is MySQL. First, verify that your MySQL server is up and running. Then, update the DATABASES const variable in settings.py.

todoapi/todoapi/settings.py

...

DATABASES = {

'default': {

# MySQL engine. Powered by the mysqlclient module.

'ENGINE': 'django.db.backends.mysql',

'NAME': 'todos',

'USER': 'root',

'PASSWORD': '',

'HOST': 'localhost',

'PORT': '3306',

}

}

...

Now we need to create the actual database for our application in MySQL. Create a database named “todos”. You can do this via the MySQL command line interface (CLI) or through some MySQL GUI program like Sequel Pro.

In your MySQL CLI or whatever tool you are using to execute SQL queries, you can run the following SQL query to create the database:

mysql> CREATE DATABASE IF NOT EXISTS todos;

To verify your database has been created, run the following, and you should see “todos” in the list of databases.

mysql> show databases;

Now that our database has been created, we can run our database migrations.

In a terminal window, run the following command, and you should all of the migrations that will be executed:

$ python manage.py showmigrations

All of the migrations above are from the middleware that comes by default from the Django library. We will not cover what they all mean in this tutorial. Read Django’s official documentation to learn more about the default middleware and how to configure them to suit your use case.

Now, to run all of those migrations at once, run the following command in a terminal window:

$ python manage.py migrate

Now that we’ve run our initial migrations, that server warning in the terminal should disappear. You may need to stop and restart Django’s development server.

Let’s start building our models for the todo items. We only need to create one table called “Todos” (see line 28 in models.py), which we will use to store our todo list data. Therefore, we will only need to create one model. In Django, a model corresponds to a database table.

In the todolist directory, open the models.py file, and update it to the following:

todoapi/todolist/models.py

This model tells Django to create a table in the database called Todos. At runtime, Django creates a Python representation of the database schema shown above, and we are given access to the database with Django’s ORM.

Next, we need to install our todolist app into our Django project. We need to update the settings.py file.

todoapi/todolist/settings.py

...

INSTALLED_APPS = [

...,

'todolist.apps.TodolistConfig',

'rest_framework’

]

...

The line todolist.apps.TodolistConfig is what connects our “todolist” app to our global Django project. The TodolistConfig module can be found in the file, todoapp/todolist/apps.py.

Now that the todolist app is wired into our Django project, we need to run a migration to create the Todos table in the database. First, we need to make a migration file, which will be located at : todoapi/todolist/migrations/0001_initial.py.

$ python manage.py makemigrations todolist

To execute the migration, run the following, and the Todos table will be created in the database:

Great! The Todos table was successfully created, and Django will create the ORM representation, so we can read and write data to the database. You can verify that the Todos table was created in MySQL.

mysql> use Todos;

mysql> show tables;

Step 6: Serializers

While handling GET requests, we need a way of transforming complex model instances (Python objects), into a JSON formatted dictionary, so we can send the data back via an HTTP response. Likewise, if a user sends data to our API via a POST or PUT request, we need a way to validate the data for integrity and security purposes before allowing that user request to add data to our database. We can achieve both of these tasks with serializers, which is a concept provided by Django Rest Framework.

It is common to utilize serializers within the context of the view layer, which you will see in the next step. For our API, we need to serialize user data for both retrieving todo items from the database as well as creating new todo items.

In your code editor, create a new file called serializers.py in the todolist app directory, and include the following code:

todoapi/todolist/serializers.py

The TodoSerializer inherits from the ModelSerializer class provided by Django Rest Framework. Since our serializer class maps directly to our Todo model class, we are able to simplify some of the validation code that would be needed if there was not an easy mapping.

This serializer does 4 things:

Validate incoming data with a max_length and required check, once the data is validated. It provides a create() method, which enables us to create a new todo item instance in the database. It provides an update() method, which enables us to update an existing todo item instance in the database. If a GET request is made to retrieve a todo item or list of todo items, we can use this serializer to transform the retrieve todo items from a Django queryset instance to a JSON formatted dictionary.

You will see all of this done in the view section in step 7.

Step 7: Views

Let’s set up our view layer. While in the todolist app directory, you should see a file called views.py. Included in this view file is the TodoList view class that will be able to handle GET, POST, PUT, and DELETE requests. I included comments in the code to explain each line.

There are many ways to design views in Django, and I could have significantly shortened the amount of code needed to handle common HTTP request such as these; however, I wanted to avoid any Django magic, so you can compare Django to a backend framework you may have built APIs with in the past.

Note, Django has a basic APIView class, which our TodoListView class inherits, but it only handles GET and POST requests. Since we also want to handle PUT and DELETE HTTP requests, we needed our API view to inherit from the UpdateModelMixin and the DestroyModelMixin, which will allow us to handle PUT and DELETE requests.

Lastly, we needed to add serializers. Provided by Django Rest Framework, serializers serve two main purposes: 1.) Serializers are used to transform Python objects into a JSON formatted dictionary and vice-versa 2.) Serializers are used to run validation logic on user submitted data.

todoapi/todolist/views.py

Step 8: URLs

We need to connect our view layer to URL endpoints. First we will create a url configuration file inside the context of the todolist app, and then we will connect our isolated todolist app’s URL file to this project’s global URL file. While inside the todolist directory, create a file called urls.py. Add the following code inside:

todoapi/todolist/urls.py

todoapi/todolist/urls.py

Let’s move back to the root directory of our Django project, and connect our todolist app’s URL routes to our projects root URL file.

We should be in the project’s root directory: todoapi/. Open the urls.py file that is located in the root directory. Update this file by connecting the paths from the todolist app’s url file:

todoapi/todoapi/urls.py

todoapi/todoapi/urls.py

Save this file, and now we should be able to visit the following endpoint to verify our view is properly connected: http://localhost:8000/todos/

Congrats! Our API is now available at our endpoints, and ready to go. Our REST API is now complete. If you have the Postman browser app, try to make GET, POST, PUT, DELETE requests to the API to test that it is working correctly.

Summary

You now know how to set up a Django server and use it exclusively as an API layer, connect MySQL to Django, and design a REST API that can handle the common HTTP requests needed in CRUD applications using Django Rest Framework.

There are many different ways to configure Models, Views, and Serializers in Django so further simplify the code above; however, I wanted to make sure the code in this tutorial was written in a generic manner without the Django magic. This way you can compare the code structure with other API web frameworks you may have used in the past such as Ruby on Rails or Express/NodeJS.



By default, Django is what is known as a Model-View-Template (MVT) framework, where you can build monolith applications that include both backend logic and front-end logic wrapped in HTTP templates. However, from the tutorial above, we are able to remove the templating layer, and simply use Django as a standalone API layer thanks to Django Rest Framework.

To build a REST API in Django and Django Rest Framework, there are three main components: models, views, and serializers, and there are many ways to configure each that was not shown in this tutorial. Feel free to dive deeper into Django Rest Framework, and I hope you found this tutorial valuable.



Note: This tutorial only includes how to build a Django REST API in a development environment. In order to deploy to production, you will need a proxy server like Nginx and a Python HTTP server like Gunicorn, which were not covered in this tutorial. See Django’s official documentation on how to deploy to production.

Full code: https://github.com/rashadrussell/beyond-light-creations/tree/master/tutorials/todolist-rest-api