Django Rest framework is a powerful toolkit for building web APIs.
What is an API?
An API (Application Programming Interface) is a set of rules shared by a particular service. These rules determine in which format and with which command set your application can access the service, as well as what data this service can return in the response. It acts as a layer between your application and external service.
REST API (Representational state transfer) is an API that uses HTTPS requests for communication with web services. From the python site, the REST API can be viewed as a data source located on an internet address that can be accessed in a certain way through certain libraries.
Types of Requests:
GET: retrieve information like a search result
POST: adds new data to the server
PUT: changes existing information
DELETE: deletes existing information
200-OK. The request was successful.
204-No content. The server successfully processed the request and did not return any content.
301-Moved permanently. The server responds that the requested page(endpoint) has been moved to another address and redirects to this address.
400-Bad request. The server cannot process the request because of the client-side errors (incorrect request format).
401-Unauthorized. Occurs when authentication failed due to incorrect credentials or even their absence.
403-Forbidden. Access to the specified resource is denied.
404-Not found. The requested resource was not found on the server.
500-Internal Server Error. Occurs when an unknown error has occurred on the server.
Enough with the theory part. Let’s see how we can create CRUD functionalities in the Django Rest framework.
I will create a small to-do list application to guide us through the process.
Steps to follow.
- Create a project and set up a virtual environment.
- Activate virtual environment
- Install Django using pip
- Create a project and an app
Create a Django Project and set up a virtual environment.
The first thing to do whenever you are creating Django projects is to set up your virtual environment where you can work in isolation. Let’s start. Install venv package to allow you to create a virtual environment. On your terminal use the following command to create virtual environment.
$ python3 -m venv env
If you ls you will see your environment created. For my case, I created env as my environment.
To activate your environment, use the following command.
After the environment is activated, let’s install Django using the pip command.
pip install django
Create a requirements.txt file to store all your installations so that the next time someone is using your applications, it will be easy to start off. An easy way to create requirements is to use the freeze command.
pip freeze > requirements.txt
And to do an installation from the requiremets.txt file, use the following command.
pip install -r requiremets.txt
Create a Django Project
To create a Django project, we use the following command.
django-admin startproject myapi .
Take note of the period in the end, it will help create a project from the current directory.
After this is done, create an app.
python manage.py startapp todoapi
The last thing before we can start our server is to go to settings.py and add your created app to the installed apps section. From here the best thing is to open your project using Visual Studio or Pycharm. For me, I will be using Pycharm.
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'todoapi',# our app ]
From here you can test if the server is running
python manage.py runserver
if you see the following as output, then we are good to continue.
System check identified no issues (0 silenced). 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. July 13, 2022 - 07:03:07 Django version 4.0.6, using settings 'myapi.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Go to the given IP address to see the outcome.
Let’s render something rather than the default Django output by adding our app to the projects urls.py section.
#myapi.urls from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('todoapi.urls')), # add this todoapi.urls ]
Also to keep our URLs neat and tidy, go to todoapi and create a urls.py
#todoapi urls.py from django.urls import path from . import views urlpatterns = [ path('', views.home, name='home'), ]
Go to todoapi views.py and create the first view of our rest API.
#todoapi/views.py from django.shortcuts import render from django.http import HttpResponse def home(request): return HttpResponse("My first api")
You are supposed to see “my first API from the browser”. This means we are good to create our API now.
Create Django Rest API
To start creating a rest API, you need to install djangorestframework and add it to your installed apps in the settings.py
pip install djangorestframework
Then you need to add it to your installed apps
INSTALLED_APPS = [ ... 'rest_framework', ]
Also you can add it to your requirements.txt file
pip freeze > requirements.txt
To begin with, we are going to use function based views therefore we need decorators. For function based views, we use
Go to models.py and add the following
#todoapi models.py from django.db import models class Todo(models.Model): title = models.CharField(max_length=150) completed = models.BooleanField(blank=True, null=True, default=False) def __str__(self): return self.title
To begin, lets create a serializers.py file in our todoapi app first.
#todoapi serializers.py from rest_framework import serializers from todoapi.models import Todo class TodoSerializer(serializers.ModelSerializer): class Meta: model = Todo fields = '__all__'
You need to make migrations for the serializer tables to be created.
$ python manage.py makemigrations $ python manage.py migrate
From here you can create admin account so that you can insert the test data. to create admin panel use the following command.
$ python manage.py createsuperuser Username (leave blank to use 'nextgen'): admin Email address: Password: Password (again): Superuser created successfully.
The next thing is to register admin in the admin dashboard. use the following.
from django.contrib import admin # Register your models here. from todoapi.models import Todo admin.site.register(Todo)
Running CRUD operations
To start performing CRUD operations, lets start with the List Operations, this will show all the todos we have in our database. List is a GET operations, so make sure to add that
Go to views.py and add the following.
@api_view(['GET']) def list_view(request): todos = Todo.objects.all() serializer = TodoSerializer(todos, many=True) return Response(serializer.data, status=status.HTTP_200_OK)
Create a url corresponding to the above view.
path('todo-list/', views.list_view, name='todo-list')
The next thing is to create a detail view, also we are going to use GET to retrieve data.
@api_view(['GET']) def detail_view(request, pk): todo = Todo.objects.get(id=pk) serializer = TodoSerializer(todo, many=False) return Response(serializer.data)
Note we are using primary key to retrieve specific item.
Create corresponding url for detail view set.
path('detail-view/<int:pk>/', views.detail_view, name='detail-view')
Here we are using POST to post data into the database. Use the following code
@api_view(['POST']) def create_view(request): serializer = TodoSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED)
Add corresponding url path
path('create-todo/', views.create_view, name='create-todo'),
For testing purposes you can use Insomnia or postman or you can stick to the one provided once you access the API on your browser.
To update a given request we use POST method. use the following code.
@api_view(['POST']) def update_view(request, pk): todo = Todo.objects.get(id=pk) serializer = TodoSerializer(instance=todo, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
Add corresponding url path
path('update-todo/<int:pk>/', views.update_view, name='update-todo'),
To use delete request, DELETE options is called. Use the following code.
@api_view(['DELETE']) def delete_view(request, pk): todo = Todo.objects.get(id=pk) todo.delete() return Response("Todo deleted successfully", status=status.HTTP_204_NO_CONTENT)
Add corresponding url path accordingly.
path('delete-todo/<int:pk>/', views.delete_view, name='delete-todo'),