Django Rest Framework with PostgreSQL: A CRUD Tutorial
Tags: python, django, postgres, computerscience
Published: 2021-02-24 17:05:53


Working with APIs is important for most web developers. From extending other services for your app to providing resources for other apps and services, APIs are essential to modern web systems for application-to-application communication.

API, an acronym for **Application Programming Interface** is a means by which the client-side interacts with the server-side to respond to the request of the user. It is a protocol that establishes how components of software communicate together.

In this tutorial, we shall go through the procedure of creating a REST API with Django and a PostgreSQL database for a customer management app. We shall set up a Django app with Django Rest Framework. Also, we will install PostgreSQL and connect it with our API. Besides, we shall perform CRUD operations (`GET`, `POST`, `PUT` and `DELETE`) on the API.

The objective of this tutorial is to create a RESTful API with CRUD capabilities on the database. We shall set up the Django REST framework, create the views and corresponding URL patterns for the APIs and 

In detail, we shall go through the following content:

- What is Django
- What is a RESTful API
- What is Django Rest Framework
- What are CRUD operations
- What is PostgreSQL

- Setting up Django Rest Framework
- Setting up PostgreSQL
- Creating up a Postgres database
- Connecting the Postgres database with the API
- Creating Views for the CRUD Operations
- Creating corresponding URL patterns for the views


## Prerequisites

- Have `Python` and `pip` package manager installed
- Have experience creating Django apps
- Have basic knowledge of Python programming
- Have basic experience using the command line



## What is Django?

Django is an open-source Python framework for building high-performance web applications. It works by the [Model-View-Controller](https://medium.com/shecodeafrica/understanding-the-mvc-pattern-in-django-edda05b9f43f) design. A notable benefit of the framework is that it enables you to build websites with speed without re-inventing the wheel. 

## What is a REST API?

RESTful API is an architectural standard for APIs that request data using HTTP. The data can be used to create, update, read, and delete resources. REST is an acronym for representational state transfer and, it uses HTTP to request data from a particular URL and, it returns the data in different formats such as JSON, HTML, etc.



## What is Django Rest Framework

Django REST framework (DRF) is an extensive and versatile toolkit for building APIs for the web. Not only is it widely used, but it is also very customizable.

## What are CRUD operations?

CRUD refers to the four basic operations - Create, Read, Update and Delete - used in relational database systems. 

CRUD enables the basic functionalities of creating, reading, updating, and deleting resources in a REST environment. The CRUD operations are usually mapped to standard HTTP methods - POST for creating, GET for reading, PUT for updating, and DELETE for deleting respectively.

From a database management perspective, the following explains how the CRUD operations work.

- CREATE: INSERT to create a new database record
- READ: SELECT to retrieve data from a database table
- UPDATE: UPDATES a record based on the specified primary key
- DELETE: DELETES a row in a database table



## What is PostgreSQL?

PostgreSQL is a free and open-source relational database system. It provides the developer with extensibility and scalability. It works with a lot of programming languages and all major operating systems such as Windows, macOS, and Linux. We will use PostgreSQL as our database for the CRUD app we will build.

## Installing PostgreSQL

You can install PostgreSQL with the following command in the terminal.
```bash
sudo apt-get update
sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib
```


On macOS, you can install `posgresql` in the `terminal` with `brew`:

```bash
brew install postgresql
```

Now, you may start up `postresql` after its installation with the following command.

```bash
brew services start postgresql
```

If you use a Windows machine, you can download a compatible  [PostgreSQL installer](https://www.postgresql.org/download/windows/) from the official website of PostgreSQL.

## Creating a Database 

 As part of the installation, PostgreSQL already created a user, `postgres` by default for carrying out administrative responsibilities. We shall change to the user to create our database and new user.

```bash
sudo su - postgres
```

`psql` gives us access to the Postgres interactive terminal where we can use the PostgreSQL queries.

```
psql
```

Now, we shall create a database for this project. Always make sure to create a separate database for each project you work on.

```
CREATE DATABASE mydb;
```

In the above command, we have used the `CREATE` command in SQL to create our database which we named `mydb`. We also ended the line with a semi-colon which comes after every command in SQL.

## Creating a Database User

Now, we shall create a database user for our database. We will call the user `myuser`. Replace `password` with a strong password below.
```
CREATE USER myuser WITH PASSWORD 'password';
```

Let us now grant access rights to our new user to enable it to work on the database.
```
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
```

We can then exit the current user's shell session and get back to the `postgres` user's session
```
\q
```

Now, let us leave the PostgreSQL interactive terminal back to the terminal.
```
exit
```

## Installing Django and Setting up a Django Project

When working with Django apps, always create new Django projects in isolated environments with virtual environment packages like `virtualenv`. Virtual environments help us to work with different versions of Python and other packages with different projects we have on our machine. Let us get the `virtualenv` package which we shall use to create our virtual environment
```bash
sudo pip install virtualenv
```

Then, let us create a folder to house our projects and change directory into the new folder.
```bash
mkdir myproject && cd myproject
```

Inside the new folder, we will create the virtual environment for our project.
```bash
virtualenv env
```

The above command provides us a duplicate of Python and some other libraries in an isolated environment. 

We will activate the virtual environment so we can use it in our project.
```bash
source env/bin/activate
```

The terminal should look like below. The name of the virtual environment will be in brackets preceding the line to show that the virtual environment has been activated.
```bash
(env) user@host:_
```

Going forward, we will install Django and set up our Django app inside the virtual environment.

```bash
pip install django djangorestframework psycopg2
```

We installed the following packages:
- `Django`: the Django package that allows us to work with the Django framework and create Django apps 
- Django Rest Framework: this toolkit gives us the features to create and use RESTful APIs with Django
- `psycopg2`: PostgreSQL package that connects our app to PostgreSQL 


Now, we shall create a Django project with the `django-admin` command.
```bash
django-admin startproject crm_project
```

`cd` into the `crm-project` directory and `cd` into the sub-directory, `crm-project`. We need to add the `rest_framework` into the `settings.py` file so it will be active in our project. Let us add it inside the `INSTALLED_APPS` list:

```
INSTALLED_APPS = [
   ...
    'rest_framework', #new
]
```

## Setting up Django Database Configuration

We have created a `PostgreSQL` database and a Django project. Now, we shall configure our Django project to use the PostgreSQL database.

Inside the `settings.py` file of the project, you will see the `DATABASES` section. It looks like the following:
```
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
```

We need to change the SQLite database configuration to the `PostgreSQL` database that we created. Therefore, replace the `DATABASES` code with the following:
```
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}
```

## Creating a Django app

Let us create an app in our Django project using `manage.py` file in the root directory of the project. It allows us to work with Django in various ways such as creating apps, creating database tables from models, running the inbuilt server, etc. Whenever you want to run the `manage.py` file, ensure that you are at the root directory where `manage.py` exists,
```bash
python manage.py startapp customer
```

If you check the directory, a new sub-directory, `customer` has been created.  Let us add the new `customer` app to the `INSTALLED_APPS` list in the `settings.py` file of our `crm-project`.

```
INSTALLED_APPS = [
   ...
    'rest_framework',
    'customer', #new
]
```

If you `cd` into customer, you would see that it has its  `models.py` and `views.py` files.


We shall create models for the `customer` app. Open the `models.py` file of the `customer` app, replace the content in it with the following code. 
```
from django.db import models

class Customer(models.Model):
    name = models.CharField("Name", max_length=240)
    email = models.EmailField()
    created = models.DateField(auto_now_add=True)

    def __str__(self):
        return self.name
```

The `Customer` class in the above code extends from Django's Model class. `CharField`, `EmailField` ,and `DateField` are appropriate data types for the respective fields.

At this point, we will create database columns with the fields of our models through the process of migration. We will use the `manage.py` file to apply the migrations.
```bash
python manage.py makemigrations
```

Then,
```bash
python manage.py migrate
```

## Creating a REST API with Django Rest Framework

We shall build our API on Django Rest Framework. We shall be dealing with views, serializers, and URL endpoints. The endpoints are attached to the views which fetch the responses to web requests.

Serializers help with translating between JSON, XML, and native Python objects. Create a new file in the `customer` directory and name it `serializers.py`. Input the following code into it.

```
from rest_framework import serializers
from .models import Customer
 
class CustomerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Customer 
        fields = ['pk', 'name', 'email', 'created']

```

The `ModelSerializer`  in the code above helps to serialize data for `Customer` objects. 


Now, we shall extend the `GenericAPIViews` that come shipped with Django Rest Framework to create our views. Add the following code inside the `views.py` of the `customer` app.
```
...
from django.shortcuts import render
from .models import Customer
from rest_framework import generics
from .serializers import CustomerSerializer


class CustomerCreate(generics.CreateAPIView):
    # API endpoint that allows creation of a new customer
	queryset = Customer.objects.all(),
	serializer_class = CustomerSerializer


class CustomerList(generics.ListAPIView):
    # API endpoint that allows customer to be viewed.
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer

```

The above code enables us to use the `CustomerCreate` view to create a new customer object, and the `CustomerList` view will be used to list all the customers in the database. 


Should in case we want to check for a single customer, we can add a `CustomerDetail` view as follows:
```
...
class CustomerDetail(generics.RetrieveAPIView):
    # API endpoint that returns a single customer by pk.
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer

```

We will include a view for the `Update` action,
```
...
class CustomerUpdate(generics.RetrieveUpdateAPIView):
    # API endpoint that allows a customer record to be updated.
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer
```

Let us add a view for the DELETE operation,
```
...
class CustomerDelete(generics.RetrieveDestroyAPIView):
    # API endpoint that allows a customer record to be deleted.
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer
```

Now, create a new `urls.py` file in the `customer` directory and add the following code to it.
```
from django.urls import include, path
from .views import CustomerCreate, CustomerList, CustomerDetail, CustomerUpdate, CustomerDelete


urlpatterns = [
	path('create/', CustomerCreate.as_view(), name='create-customer'),
    path('', CustomerList.as_view()),
    path('<int:pk>/', CustomerDetail.as_view(), name='retrieve-customer'),
    path('update/<int:pk>/', CustomerUpdate.as_view(), name='update-customer'),
    # path('delete/<int:pk>/', CustomerDelete.as_view(), name='delete-customer')
]
```

Each of the endpoints handles a particular HTTP method. The first endpoint handles the `POST` method for CREATE operation. The second and third endpoints handle the `GET` method for READ operations. The fourth endpoint handles the `PUT` method for UPDATE operation while the last endpoint handles the `DELETE` operation.

Notwithstanding, we still need to point the root `urls.py` file to the `urls.py` file of the `customer` app. Let us go back to the `crm_project` sub-directory and open the `urls.py` file there. We will then include the `customer` app endpoints.
```
from django.contrib import admin
from django.urls import path, include #new

urlpatterns = [
    path('admin/', admin.site.urls),
    path('customer/', include('customer.urls')), #new
]
```
The file already contained the `urlpattern` for the Django-admin app which gives us administrator capabilities.


Django ships with an inbuilt server that could be used for testing purposes. We will run our application now through the server with the following command:
```bash
python manage.py runserver
```

Let us go to the URL http://127.0.0.1:8000/customer on the browser and we shall the interface of the Browsable API. Browsable API comes with REST Framework and allows us to interact with our API in the absence of a client-side app. We can visit each of the routes earlier defined in the `urlpatterns` of our `customer` app and perform the CRUD operations.  

The Browsable API looks like the following for the _customer-create_ endpoint at  http://127.0.0.1:8000/customer/create

![customer-create](C:\Users\JheiKhei\Desktop\customer-create.JPG)



## Conclusion

Well-done! We have learned how to set up a Rest API with Django connected to a PostgreSQL database. You can get the full code of the tutorial project [here](https://github.com/J-rayX/crm_project).

This tutorial helped us to build a RESTful API with the Django REST framework. We also learned how to set up PostgreSQL for a Django project. We used the command-line to create PostgreSQL databases and users. We connected the PostgreSQL database to a basic Django customer management application and added CRUD functionalities to the API. 

With what we have learned, we should be able to create APIs in our web projects. We would also be able to learn more about API development.  Thanks for your time. Kindly ask questions and share your ideas and suggestions.

**[Twitter](https://twitter.com/JKayLight) | [LinkedIn](https://www.linkedin.com/in/jekayinoluwa/)**