Skip to main content

Django REST Introduction

What is Django REST Framework?

Django REST Framework (DRF) is a powerful and flexible toolkit built on top of Django that makes it easy to build Web APIs. If you're familiar with Django's traditional approach to building web applications, DRF extends this functionality to easily create RESTful APIs that can serve your application's data to various clients including mobile applications, JavaScript frameworks, or other services.

REST (Representational State Transfer) is an architectural style for designing networked applications. RESTful APIs use HTTP requests to perform CRUD (Create, Read, Update, Delete) operations on resources, typically represented in formats like JSON or XML.

Why Use Django REST Framework?

  • Web Browsable API: DRF provides a browsable web API, making development and testing much easier
  • Authentication Policies: Includes OAuth1, OAuth2, Basic Authentication, and more
  • Serialization: Powerful serialization that supports both ORM and non-ORM data sources
  • Extensive Documentation: Well-documented with many tutorials and examples
  • Community & Ecosystem: Large community and extensive ecosystem of packages

Setting Up Django REST Framework

Let's start by setting up a new Django project with REST Framework:

Installation

bash
# Create a virtual environment
python -m venv env
source env/bin/activate # On Windows: env\Scripts\activate

# Install Django and Django REST Framework
pip install django djangorestframework

Project Setup

bash
# Create a new Django project
django-admin startproject tutorial
cd tutorial

# Create an app
python manage.py startapp api

Configure Django REST Framework

Update your settings.py to include REST Framework:

python
# tutorial/settings.py

INSTALLED_APPS = [
# Django apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

# Third-party apps
'rest_framework', # Add this line

# Your apps
'api',
]

# Add REST Framework settings
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}

Creating Your First API

Let's create a simple API for a book library system. We'll follow these steps:

  1. Define models
  2. Create serializers
  3. Set up views
  4. Configure URLs

1. Define Models

First, let's create a simple Book model:

python
# api/models.py
from django.db import models

class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
publication_date = models.DateField()
isbn = models.CharField(max_length=13, unique=True)

def __str__(self):
return self.title

Run migrations to create the database table:

bash
python manage.py makemigrations
python manage.py migrate

2. Create Serializers

Serializers in DRF convert complex data like querysets and model instances to Python datatypes that can then be easily rendered into JSON, XML, or other content types.

python
# api/serializers.py
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date', 'isbn']

This BookSerializer automatically creates fields corresponding to the Book model and provides validation, create, and update operations.

3. Set Up Views

DRF offers several types of views. Here, we'll use ViewSets which provide CRUD operations with minimal code:

python
# api/views.py
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer

class BookViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows books to be viewed or edited.
"""
queryset = Book.objects.all().order_by('-publication_date')
serializer_class = BookSerializer

The ModelViewSet class automatically provides .list(), .retrieve(), .create(), .update(), and .destroy() actions.

4. Configure URLs

Now set up the URLs to access your API:

python
# tutorial/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from api.views import BookViewSet

# Create a router and register our viewsets
router = routers.DefaultRouter()
router.register(r'books', BookViewSet)

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

Testing Your API

Run your server with:

bash
python manage.py runserver

Now you can access your API at:

Try accessing this URL in your browser. You should see DRF's browsable API interface:

The browsable API allows you to:

  1. View all books (GET)
  2. Create new books (POST)
  3. View individual books (GET with ID)
  4. Update books (PUT/PATCH)
  5. Delete books (DELETE)

Making API Requests

Using the Browsable API

With the browsable API, you can interact directly through your browser:

  1. List all books: Visit http://127.0.0.1:8000/api/books/
  2. Create a new book: Fill out the form at the bottom of the page
  3. View a book: Click on a book's URL (e.g., http://127.0.0.1:8000/api/books/1/)
  4. Update/Delete: Use the forms provided on the detail page

Using cURL

You can also use cURL to interact with your API:

GET all books:

bash
curl -X GET http://127.0.0.1:8000/api/books/

POST a new book:

bash
curl -X POST http://127.0.0.1:8000/api/books/ \
-H "Content-Type: application/json" \
-d '{"title": "Django for Beginners", "author": "William S. Vincent", "publication_date": "2020-01-01", "isbn": "9781234567890"}'

GET a specific book:

bash
curl -X GET http://127.0.0.1:8000/api/books/1/

PUT (update) a book:

bash
curl -X PUT http://127.0.0.1:8000/api/books/1/ \
-H "Content-Type: application/json" \
-d '{"title": "Django for Professionals", "author": "William S. Vincent", "publication_date": "2020-04-01", "isbn": "9781234567890"}'

DELETE a book:

bash
curl -X DELETE http://127.0.0.1:8000/api/books/1/

Real-world Application: Building a To-Do API

Let's expand our knowledge by creating a simple To-Do API:

Model

python
# api/models.py
from django.db import models

class Task(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(blank=True)
completed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
return self.title

Serializer

python
# api/serializers.py
from rest_framework import serializers
from .models import Task

class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ['id', 'title', 'description', 'completed', 'created_at']

Views

DRF offers different ways to create API views. Let's see three different approaches:

1. Using Function-Based Views

python
# api/views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Task
from .serializers import TaskSerializer

@api_view(['GET', 'POST'])
def task_list(request):
"""
List all tasks, or create a new task.
"""
if request.method == 'GET':
tasks = Task.objects.all()
serializer = TaskSerializer(tasks, many=True)
return Response(serializer.data)

elif request.method == 'POST':
serializer = TaskSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

2. Using Class-Based Views

python
# api/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Task
from .serializers import TaskSerializer

class TaskListView(APIView):
"""
List all tasks, or create a new task.
"""
def get(self, request, format=None):
tasks = Task.objects.all()
serializer = TaskSerializer(tasks, many=True)
return Response(serializer.data)

def post(self, request, format=None):
serializer = TaskSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

3. Using ViewSets (most concise)

python
# api/views.py
from rest_framework import viewsets
from .models import Task
from .serializers import TaskSerializer

class TaskViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
"""
queryset = Task.objects.all()
serializer_class = TaskSerializer

URLs Configuration

With ViewSets, URL configuration is very simple:

python
# tutorial/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from api.views import TaskViewSet

router = DefaultRouter()
router.register(r'tasks', TaskViewSet)

urlpatterns = [
path('api/', include(router.urls)),
]

Authentication and Permissions

When building APIs, you often need to restrict access. DRF provides various authentication and permission classes.

Adding Basic Authentication

Update your settings.py:

python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}

Using Token Authentication

  1. Add 'rest_framework.authtoken' to your INSTALLED_APPS in settings.py
  2. Run python manage.py migrate to create the token table
  3. Update your authentication classes:
python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
}
  1. Create a token for a user:
python
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User

user = User.objects.get(username='your_username')
token = Token.objects.create(user=user)
print(token.key)
  1. To use the token in requests, add the header:
Authorization: Token your_token_key

Pagination

As your API grows, you'll want to paginate your results:

python
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}

Summary

In this introduction to Django REST Framework, we've covered:

  1. Setting up Django REST Framework in a project
  2. Creating models and serializers
  3. Building views using different approaches (function-based, class-based, ViewSets)
  4. Configuring URLs and routers
  5. Testing APIs using the browsable API and cURL
  6. Adding authentication and permissions
  7. Implementing pagination

Django REST Framework simplifies building powerful and flexible APIs. With minimal code, you can create a complete RESTful API with browsable endpoints, authentication, and serialization.

Additional Resources

Exercises

  1. Extend the Book API to include a "Category" model with a one-to-many relationship (a book belongs to a category)
  2. Implement token authentication for your API
  3. Add search functionality to filter books by title or author
  4. Create a custom permission class that only allows book creators to modify their books
  5. Build a nested serializer to display related data (like showing category details when requesting a book)

By completing these exercises, you'll gain practical experience with many of Django REST Framework's powerful features!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)