Python Django REST Framework (DRF) tutorial – If you’re a Python developer looking to expose your Django models as powerful, standards‑compliant APIs, you’ve landed in the right place. In this step‑by‑step guide we’ll walk through everything you need to know to build, test, and secure a RESTful API with Django REST Framework. From project setup to serializers, viewsets, routers, authentication, and best‑practice tips, this tutorial covers the full stack so you can launch production‑ready endpoints in minutes.
Why Choose Django REST Framework?
- Built for Django: DRF integrates seamlessly with Django’s ORM, authentication system, and admin.
- Rich feature set: Automatic URL routing, browsable API, pagination, filtering, and content negotiation.
- Extensible: Plug‑in custom renderers, parsers, throttling, and permission classes.
- Strong community: Extensive documentation, tutorials, and third‑party packages.
Project Setup – Getting the Foundations Right
1. Create a virtual environment
python -m venv env
source env/bin/activate # On Windows use `env\Scripts\activate`
2. Install Django and DRF
pip install django djangorestframework
3. Start a new Django project
django-admin startproject myapi
cd myapi
python manage.py startapp blog
4. Register apps
Add 'rest_framework' and your new 'blog' app to INSTALLED_APPS in myapi/settings.py:
INSTALLED_APPS = [
# default Django apps …
'rest_framework',
'blog',
]
Modeling Data – The First Building Block
Let’s create a simple Post model to represent blog entries.
# blog/models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
author = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Run migrations to create the table:
python manage.py makemigrations
python manage.py migrate
Serializers – Converting Django Objects to JSON
A serializer defines how model instances are turned into JSON (or other formats) and vice‑versa.
# blog/serializers.py
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'title', 'body', 'author', 'created']
Views – The Logic Behind Each Endpoint
DRF provides several view styles. For most CRUD APIs, ModelViewSet is the most concise.
# blog/views.py
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows posts to be viewed or edited.
"""
queryset = Post.objects.all().order_by('-created')
serializer_class = PostSerializer
Routing – Mapping URLs to Views Automatically
Using DefaultRouter DRF can generate a full set of routes (list, create, retrieve, update, delete) with a single line.
# blog/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet
router = DefaultRouter()
router.register(r'posts', PostViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Don’t forget to include the app’s URLs in the project’s root:
# myapi/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('blog.urls')), # <-- API root
]
Testing the API – The Browsable Interface
Start the development server:
python manage.py runserver
Navigate to http://127.0.0.1:8000/api/posts/. DRF’s browsable API lets you:
- View a list of posts in JSON or HTML.
- Submit POST, PUT, PATCH, and DELETE requests directly from the browser.
- Inspect request/response headers for debugging.
Adding Authentication and Permissions
Secure your API by enabling token‑based authentication and restricting actions.
1. Install the token package
pip install djangorestframework-simplejwt
2. Update settings
# myapi/settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
),
}
3. Create token endpoints
# myapi/urls.py (add below existing patterns)
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns += [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
4. Test with curl
# Obtain a token
curl -X POST -H "Content-Type: application/json" \
-d '{"username":"admin","password":"adminpwd"}' \
http://127.0.0.1:8000/api/token/
# Use the token to create a post
curl -X POST -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"title":"First Post","body":"Hello DRF!","author":"Alice"}' \
http://127.0.0.1:8000/api/posts/
Advanced Features You’ll Love
- Pagination: Set
PAGE_SIZEin settings or useLimitOffsetPaginationper view. - Filtering: Integrate
django-filterto enable URL‑based query parameters (e.g.,?author=Alice). - Versioning: Prefix URLs with
/v1/,/v2/or use Accept‑Header versioning for backward compatibility. - Custom Actions: Add @action‑decorated methods in a viewset for non‑CRUD endpoints (e.g.,
/posts/{id}/publish/).
Best Practices for a Production‑Ready DRF API
- Separate serializers from models: Keep business logic out of serializers; use
validate_*methods for field‑level checks. - Use viewsets and routers: Reduces boilerplate and guarantees a consistent URL scheme.
- Limit exposure: Apply
IsAdminUseror custom permission classes to sensitive endpoints. - Document with OpenAPI/Swagger: Install
drf-yasgordrf-spectacularto generate interactive API docs. - Cache expensive queries: Leverage Django’s cache framework or DRF’s
CacheResponseMixinfor read‑heavy resources. - Write tests: Use
APITestCaseto assert response codes, data shapes, and permission enforcement. - Monitor performance: Enable Django’s
django‑silkor external APM tools to track latency.
Deploying Your DRF Application
When you’re ready to go live, follow these deployment steps:
- Choose a WSGI server such as
gunicornoruwsgi. - Place the app behind a reverse proxy (NGINX or Apache) for static file handling and SSL termination.
- Set
DEBUG = Falseand configureALLOWED_HOSTS. - Use a PostgreSQL or MySQL database for production instead of SQLite.
- Configure environment variables for secret keys, database credentials, and JWT signing keys.
Conclusion
Building a robust API with Python Django REST Framework is both fast and scalable. By following this tutorial you’ve learned how to set up a Django project, define models, serialize data, expose CRUD endpoints with viewsets, secure them with JWT authentication, and adopt best practices for production readiness. Whether you’re creating a mobile backend, a microservice, or a public API, DRF gives you the tools to deliver clean, maintainable, and performant RESTful services. Keep experimenting with