A REST API allows applications to communicate with each other using HTTP. Instead of returning complete HTML pages, an API commonly returns data in a machine-readable format such as JSON.
In Django, the most commonly used toolkit for building REST APIs is Django REST Framework (DRF). It provides serializers, API views, authentication tools, permissions, routers, and many other features for building APIs.
pip.
API stands for Application Programming Interface. An API provides a way for different software applications to communicate.
For example, a mobile application can request student data from a Django server through an API.
Mobile App
↓
HTTP Request
↓
Django API
↓
Database
↓
JSON Response
↓
Mobile App
REST stands for Representational State Transfer. It is an architectural style commonly used for designing web APIs.
REST APIs generally use HTTP methods such as:
Django REST Framework, commonly called DRF, is a powerful toolkit for building Web APIs with Django.
It provides:
Install Django REST Framework using pip:
pip install djangorestframework
After installation, add it to INSTALLED_APPS.
INSTALLED_APPS = [
...
"rest_framework",
]
You can create a separate Django application for API functionality.
python manage.py startapp api
Then add the app:
INSTALLED_APPS = [
...
"api",
"rest_framework",
]
JSON is commonly used to exchange data between clients and APIs.
{
"id": 1,
"name": "Rahul",
"course": "Python"
}
A mobile application, JavaScript application, or another server can consume this data.
GET is commonly used to retrieve data from an API.
GET /api/students/
For example, this endpoint could return a list of students.
POST is commonly used to send data to an API to create a new resource.
POST /api/students/
The request body might contain:
{
"name": "Rahul",
"course": "Python"
}
PUT is commonly used to replace an existing resource with a new representation.
PUT /api/students/1/
The request can contain the fields required for the updated resource.
PATCH is commonly used for a partial update.
PATCH /api/students/1/
For example, only the course may be changed:
{
"course": "Django"
}
DELETE is commonly used to remove a resource.
DELETE /api/students/1/
The API can delete the student with ID 1.
For our API example, create a Student model.
from django.db import models
class Student(models.Model):
name = models.CharField(
max_length=100
)
email = models.EmailField()
course = models.CharField(
max_length=100
)
age = models.IntegerField()
def __str__(self):
return self.name
Run migrations after creating the model.
python manage.py makemigrations
python manage.py migrate
A serializer converts complex Django objects, such as model instances, into native Python data types that can then be rendered as JSON.
It can also validate incoming data and convert validated data into model instances.
Create a serializer in api/serializers.py.
from rest_framework import serializers
from .models import Student
class StudentSerializer(
serializers.ModelSerializer
):
class Meta:
model = Student
fields = [
"id",
"name",
"email",
"course",
"age"
]
ModelSerializer can automatically generate fields and useful
default behavior based on a Django model.
Django REST Framework provides APIView for creating
class-based API endpoints.
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Student
from .serializers import StudentSerializer
class StudentListAPIView(APIView):
def get(self, request):
students = Student.objects.all()
serializer = StudentSerializer(
students,
many=True
)
return Response(
serializer.data
)
Create api/urls.py.
from django.urls import path
from .views import StudentListAPIView
urlpatterns = [
path(
"students/",
StudentListAPIView.as_view(),
name="student-api"
),
]
Include these URLs in the main project's URL configuration.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path(
"admin/",
admin.site.urls
),
path(
"api/",
include("api.urls")
),
]
The API endpoint will now be available at:
/api/students/
If the database contains students, a GET request can return JSON-like data.
[
{
"id": 1,
"name": "Rahul",
"email": "rahul@example.com",
"course": "Python",
"age": 21
},
{
"id": 2,
"name": "Priya",
"email": "priya@example.com",
"course": "Django",
"age": 22
}
]
The APIView can also handle POST requests.
def post(self, request):
serializer = StudentSerializer(
data=request.data
)
if serializer.is_valid():
serializer.save()
return Response(
serializer.data,
status=201
)
return Response(
serializer.errors,
status=400
)
The serializer validates the incoming data before saving it.
Before saving incoming API data, call is_valid().
serializer = StudentSerializer(
data=request.data
)
if serializer.is_valid():
serializer.save()
Validation errors can be returned to the API client.
return Response(
serializer.errors,
status=400
)
A detail API can retrieve, update, or delete one student.
from django.shortcuts import get_object_or_404
class StudentDetailAPIView(APIView):
def get(self, request, id):
student = get_object_or_404(
Student,
id=id
)
serializer = StudentSerializer(
student
)
return Response(
serializer.data
)
APIs often need authentication so that only authorized clients or users can access protected resources.
Django REST Framework supports several authentication approaches, including:
The appropriate authentication method depends on the application.
Authentication identifies the requester. Permissions determine whether that requester is allowed to perform an action.
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class StudentAPIView(APIView):
permission_classes = [
IsAuthenticated
]
This requires an authenticated user for the API view.
Django REST Framework provides ViewSets that can group related API operations together.
from rest_framework.viewsets import ModelViewSet
class StudentViewSet(
ModelViewSet
):
queryset = Student.objects.all()
serializer_class = StudentSerializer
A ModelViewSet can provide common CRUD operations with less code.
Routers can automatically create URL patterns for ViewSets.
from rest_framework.routers import DefaultRouter
from .views import StudentViewSet
router = DefaultRouter()
router.register(
"students",
StudentViewSet
)
urlpatterns = router.urls
This can reduce the amount of URL configuration required for standard CRUD APIs.
Large API responses can be divided into pages using Django REST Framework's pagination features.
For example, an API may return a limited number of students per response instead of returning every student at once.
REST_FRAMEWORK = {
"PAGE_SIZE": 10
}
Pagination configuration can be customized according to the project's requirements.
An API can be tested using tools such as a browser for simple GET requests, or API clients for different HTTP methods.
Example endpoint:
GET /api/students/
For a POST request, send JSON data such as:
{
"name": "Amit",
"email": "amit@example.com",
"course": "Django",
"age": 22
}
api_project/
│
├── manage.py
│
├── api_project/
│ ├── settings.py
│ ├── urls.py
│ ├── asgi.py
│ └── wsgi.py
│
└── api/
├── migrations/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── serializers.py
├── urls.py
├── views.py
└── tests.py
Client Application
↓
HTTP Request
↓
Django URL
↓
API View / ViewSet
↓
Serializer
↓
Django Model / ORM
↓
Database
↓
Serializer
↓
JSON Response
↓
Client Application
This workflow is the foundation of many Django REST API applications.
Django REST Framework provides a complete toolkit for creating APIs with Django.
Question: Which Django toolkit is commonly used to build REST APIs?