Welcome to the ultimate Python Django REST Framework (DRF) tutorial! Whether you’re a seasoned Django developer or just dipping your toes into API development, this guide will walk you through every essential step—from setting up your environment to building a production‑ready RESTful API. By the end, you’ll have a solid grasp of DRF’s core components, best practices, and how to deliver scalable, secure APIs that search engines love. Let’s dive in and transform your Django projects into powerful data‑driven services.
What Is Django REST Framework?
Django REST Framework is a flexible, modular toolkit for building Web APIs on top of the Django ecosystem. It abstracts away much of the boilerplate involved in serialization, request handling, and authentication, letting you focus on business logic. DRF is widely adopted because it integrates seamlessly with Django’s ORM, supports both function‑based and class‑based views, and provides a browsable API that’s perfect for debugging and documentation.
Core Concepts You Need to Know
- Serializers: Convert complex Django model instances into native Python data types (and vice‑versa) for JSON, XML, or other formats.
- ViewSets: Combine the logic for a set of related views (list, retrieve, create, update, delete) into a single class.
- Routers: Automatically generate URL patterns for ViewSets, reducing manual routing work.
- Authentication & Permissions: Control who can access your API and what actions they can perform.
- Browsable API: An HTML interface that lets developers explore endpoints directly from a web browser.
Setting Up the Development Environment
Prerequisites
Before you start, make sure you have the following installed:
- Python 3.9+ (preferably via
pyenvor a virtual environment) - pip (Python package installer)
- Git (optional, but recommended for version control)
- A code editor such as VS Code or PyCharm
Installing Django and DRF
# Create and activate a virtual environment
python -m venv env
source env/bin/activate # On Windows use `env\Scripts\activate`
# Upgrade pip and install Django with DRF
pip install --upgrade pip
pip install django djangorestframework
Once installed, verify the versions:
python -c "import django, rest_framework; print('Django', django.get_version(), 'DRF', rest_framework.__version__)"
Building Your First API
1. Create a Django Project
django-admin startproject myproject
cd myproject
2. Create an App
python manage.py startapp blog
Don’t forget to add 'blog' and 'rest_framework' to INSTALLED_APPS in myproject/settings.py:
INSTALLED_APPS = [
# default Django apps …
'rest_framework',
'blog',
]
3. Define a Model
In blog/models.py create a simple Post model:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
4. Create a Serializer
Serializers translate model instances to JSON. Add blog/serializers.py:
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'title', 'content', 'created_at']
5. Build Views with ViewSets
In blog/views.py use a ModelViewSet to get CRUD operations for free:
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all().order_by('-created_at')
serializer_class = PostSerializer
6. Register Routes with Routers
DRF routers automatically generate the URL conf. Edit myproject/urls.py:
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from blog.views import PostViewSet
router = routers.DefaultRouter()
router.register(r'posts', PostViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
path('api-auth/', include('rest_framework.urls')), # optional login UI
]
7. Migrate and Test
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
Visit http://127.0.0.1:8000/api/posts/ in your browser. You’ll see the DRF browsable API, allowing you to list, create, and edit posts without writing any extra HTML.
Handling Authentication and Permissions
Securing an API is as important as building it. DRF provides several out‑of‑the‑box authentication schemes and a flexible permission system.
Common Authentication Methods
- SessionAuthentication: Uses Django’s session framework; great for web‑based clients.
- TokenAuthentication: Issues a simple token per user; ideal for mobile apps.
- JWTAuthentication: JSON Web Tokens provide stateless, scalable auth (requires
djangorestframework-simplejwt).
Setting Up Token Authentication
# Install the token package
pip install djangorestframework-authtoken
# Add to INSTALLED_APPS
INSTALLED_APPS += ['rest_framework.authtoken']
# Migrate
python manage.py migrate
# Update REST_FRAMEWORK settings (myproject/settings.py)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
Create a token for a user via the admin or the command line:
python manage.py drf_create_token your_username
Permission Classes You’ll Use Frequently
AllowAny– Open to all (useful for public read‑only endpoints).IsAuthenticated– Requires a valid user.IsAdminUser– Restricts access to staff/superusers.IsOwnerOrReadOnly– Custom class that lets owners edit, others only read.
Testing Your API
Automated testing ensures your API behaves as expected. DRF extends Django’s test client with JSON support.
from rest_framework.test import APITestCase
from django.urls import reverse
from .models import Post
from django.contrib.auth.models import User
class PostAPITest(APITestCase):
def setUp(self):
self.user = User.objects.create_user(username='tester', password='pass')
self.client.login(username='tester', password='pass')
self.post = Post.objects.create(title='First', content='Hello World')
def test_list_posts(self):
url = reverse('post-list') # auto‑generated by router
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
def test_create_post(self):
url = reverse('post-list')
data = {'title': 'New Post', 'content': 'Content here'}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, 201)
self.assertEqual(Post.objects.count(), 2)
Leave a Reply