Python Django Rest Framework Drf Tutorial

Written by

in

Looking to turn your Django web app into a powerful, scalable API? The Django REST Framework (DRF) makes it effortless to build RESTful services with Python, offering a clean, modular approach that blends perfectly with Django’s “batteries‑included” philosophy. In this comprehensive tutorial we’ll walk through everything you need to know— from setting up the environment to deploying a production‑ready API—so you can start delivering data to web, mobile, and IoT clients in no time.

What Is Django REST Framework?

Django REST Framework (often abbreviated as DRF) is an open‑source library that extends Django’s core capabilities to create web APIs. It provides:

  • Powerful Serializer classes for converting complex data types (models, querysets) to JSON, XML, or other formats.
  • Flexible ViewSet and Router abstractions that reduce boilerplate code.
  • Built‑in support for authentication (Token, JWT, OAuth), permissions, throttling, and pagination.
  • Browsable API documentation that helps developers test endpoints directly from the browser.

Because DRF is built on top of Django, you can reuse your existing models, middleware, and settings while gaining a full‑featured API layer.

Setting Up the Development Environment

Before diving into code, make sure your workstation is ready. Follow these steps:

  1. Install Python 3.11+ – most modern Django projects require a recent Python version.
  2. Create a virtual environment to isolate dependencies:
    python -m venv venv
    source venv/bin/activate   # Linux/macOS
    venv\Scripts\activate      # Windows
  3. Upgrade pip and install Django and DRF:
    pip install --upgrade pip
    pip install django djangorestframework
  4. Optional but recommended: install django-filter for advanced query filtering and drf-yasg for Swagger/OpenAPI docs.
    pip install django-filter drf-yasg

Creating a New Django Project

With the environment ready, start a fresh Django project:

django-admin startproject myapi
cd myapi

Then create a reusable app where the API lives:

python manage.py startapp books

Don’t forget to add the new app and DRF to INSTALLED_APPS in myapi/settings.py:

INSTALLED_APPS = [
    # default Django apps...
    'rest_framework',
    'books',
]

Building Your First API with DRF

We’ll build a simple “Bookstore” API that lets clients list, create, retrieve, update, and delete books. First, define a model in books/models.py:

from django.db import models

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

    def __str__(self):
        return f"{self.title} by {self.author}"

Run migrations:

python manage.py makemigrations
python manage.py migrate

Serializers Explained

Serializers translate model instances into JSON and validate incoming data. Create books/serializers.py:

from rest_framework import serializers
from .models import Book

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

The ModelSerializer automatically generates fields based on the model, saving you time.

ViewSets and Routers

Instead of writing separate view functions for each CRUD operation, DRF’s ViewSet bundles them together. Add books/views.py:

from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

Now wire the viewset to URLs using a router. In books/urls.py:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet

router = DefaultRouter()
router.register(r'books', BookViewSet, basename='book')

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

Finally, include the app’s URLs in the project’s myapi/urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('books.urls')),
]

Authentication and Permissions

APIs rarely stay open to the world. DRF provides several authentication schemes out of the box. For a quick start, enable token authentication:

pip install djangorestframework-simplejwt

Update myapi/settings.py with the authentication classes:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

Generate JWT tokens via the provided endpoints (you’ll add them later) and protect the BookViewSet by inheriting from IsAuthenticatedOrReadOnly if you want public read access but restricted writes:

from rest_framework.permissions import IsAuthenticatedOrReadOnly

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [IsAuthenticatedOrReadOnly]

Testing Your API

Automated tests ensure your API behaves as expected. DRF ships with an API test client that extends Django’s Client. Example in books/tests.py:

from rest_framework.test import APITestCase
from django.urls import reverse
from .models import Book

class BookAPITest(APITestCase):
    def setUp(self):
        self.book = Book.objects.create(
            title='Django for APIs',
            author='John Doe',
            published_date='2023-01-01',
            isbn='1234567890123'
        )
        self.list_url = reverse('book-list')

    def test_list_books(self):
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(len(response.data), 1)

    def test_create_book_unauthenticated(self):
        data = {
            'title': 'New Book',
            'author': 'Jane Smith',
            'published_date': '2024-05-10',
            'isbn': '9876543210987'
        }
        response = self.client.post(self.list_url, data, format='json')
        self.assertEqual(response.status_code, 401)  # Unauthorized

Best Practices and Performance Tips

  • Use Select Related / Prefetch Related in viewsets to avoid N+1 query problems.
  • Limit Fields with fields Query Parameter for large objects—DRF’s DynamicFieldsModelSerializer pattern helps.
  • Implement Pagination (PageNumber, LimitOffset, or Cursor) to keep responses lightweight.
  • Cache Frequently Accessed Endpoints using Django’s cache framework or third‑party solutions like Redis.
  • Document Your API with Swagger/OpenAPI via drf-yasg or drf-spectacular for developer-friendly docs.
  • Version Your API from day one (e.g., /api/v1/) to simplify future upgrades.

Deploying the DRF Application

When you’re ready to go live, follow these production steps:

  1. Switch DEBUG = False and configure ALLOWED_HOSTS.
  2. Set up a robust database (PostgreSQL is the de‑facto standard).
  3. Use gunicorn or uvicorn as the WSGI/ASGI server.
  4. Serve static files with whitenoise or a dedicated CDN.
  5. Secure the API with HTTPS (Let’s Encrypt provides free certificates).
  6. Consider containerizing with Docker for consistent deployments.

Conclusion

Whether you’re building a simple mobile backend or a complex micro‑service architecture, Django REST Framework gives you the tools to deliver fast, secure, and maintainable APIs with minimal code. By mastering serializers, viewsets, routers, and authentication, you’ll be able to expose your Django models as clean

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *