H M < >
CMM721

Django REST Framework

Session 8

Learning Objectives

  • Understand REST API principles
  • Install and configure Django REST Framework
  • Create serializers for data validation
  • Build API views and viewsets
  • Implement authentication and permissions
  • Test APIs using browsable API and Postman

What is REST?

REST: Representational State Transfer

Key Principles:

  • Stateless: Each request contains all information needed
  • Resource-based: Everything is a resource with a URI
  • HTTP Methods: GET, POST, PUT, PATCH, DELETE
  • JSON Format: Standard data exchange format

Example REST API:

GET https://api.example.com/posts/
POST https://api.example.com/posts/

Django REST Framework (DRF)

Installation:

# Install DRF
pip install djangorestframework
# Add to INSTALLED_APPS in settings.py
INSTALLED_APPS = [
...
'rest_framework',
]
# Add REST Framework settings
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}

Serializers

Serializer: Converts complex data (models) ↔ JSON
# serializers.py
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.username', read_only=True)
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author', 'author_name', 'created_at']
read_only_fields = ['id', 'created_at']

🎯 Serialization Example

Django Model → JSON

Python Object

post = Post(
  id=1,
  title="Django REST",
  content="API tutorial",
  author=user
)

JSON Response

{
  "id": 1,
  "title": "Django REST",
  "content": "API tutorial",
  "author": 5,
  "created_at": "2024-01-15"
}

API Views

Function-Based View:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['GET', 'POST'])
def post_list(request):
if request.method == 'GET':
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = PostSerializer(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)

Class-Based Views

from rest_framework import generics
class PostListCreate(generics.ListCreateAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
class PostDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer

URL Configuration:

from django.urls import path
from . import views
urlpatterns = [
path('api/posts/', views.PostListCreate.as_view()),
path('api/posts/<int:pk>/', views.PostDetail.as_view()),
]

ViewSets and Routers

# views.py
from rest_framework import viewsets
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
# urls.py
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register(r'posts', views.PostViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
Result: Automatic CRUD endpoints with minimal code!

🎯 API Endpoint Overview

Generated Endpoints

GET /api/posts/ List all posts
POST /api/posts/ Create new post
GET /api/posts/1/ Retrieve post #1
PUT /api/posts/1/ Update post #1
DELETE /api/posts/1/ Delete post #1

Task 1: Build REST API

Objective:

Create a complete REST API for your blog

Requirements:

  1. Install Django REST Framework
  2. Create PostSerializer with all fields
  3. Create CommentSerializer
  4. Implement ViewSets for Post and Comment
  5. Configure router for automatic URL generation
  6. Test all endpoints in browsable API
  7. Ensure proper JSON responses

Test Endpoints:

  • GET /api/posts/ - List posts
  • POST /api/posts/ - Create post
  • GET /api/posts/1/ - Detail view
  • PUT /api/posts/1/ - Update
  • DELETE /api/posts/1/ - Delete

Authentication

Token Authentication:

# settings.py
INSTALLED_APPS = [
...
'rest_framework.authtoken',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}
# Generate token for user
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=user)
print(token.key)

Permissions

from rest_framework import permissions
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)

Built-in Permissions:

  • AllowAny: No restrictions
  • IsAuthenticated: Must be logged in
  • IsAuthenticatedOrReadOnly: Read for all, write for authenticated
  • IsAdminUser: Admin only

Custom Permissions

from rest_framework import permissions
class IsAuthorOrReadOnly(permissions.BasePermission):
"""
Custom permission: only author can edit/delete
"""
def has_object_permission(self, request, view, obj):
# Read permissions allowed for any request
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions only for author
return obj.author == request.user
# Usage
class PostViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthorOrReadOnly]

Filtering and Search

# Install
pip install django-filter
# Add to INSTALLED_APPS
INSTALLED_APPS = [
...
'django_filters',
]
# ViewSet with filtering
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['author', 'published']
search_fields = ['title', 'content']

Task 2: Authentication & Permissions

Objective:

Add authentication and authorization to your API

Requirements:

  1. Implement Token Authentication
  2. Create login/logout endpoints
  3. Add IsAuthenticatedOrReadOnly to posts
  4. Create custom IsAuthorOrReadOnly permission
  5. Automatically assign author on post creation
  6. Add filtering by author and published status
  7. Implement search on title and content
  8. Test with authenticated and anonymous users

Bonus:

  • Add user registration endpoint
  • Implement pagination
  • Add ordering by date

🎯 Testing with Browsable API

DRF Browsable API Features

  • Interactive Interface: Test API directly in browser
  • JSON/HTML Toggle: View responses in different formats
  • Login/Logout: Built-in authentication UI
  • Forms: Automatically generated for POST/PUT
  • OPTIONS: See available actions and fields

Try it:

http://127.0.0.1:8000/api/posts/

Testing with Postman

GET Request:

GET http://127.0.0.1:8000/api/posts/
Headers:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

POST Request:

POST http://127.0.0.1:8000/api/posts/
Headers:
Content-Type: application/json
Authorization: Token 9944b09...
Body:
{
"title": "New Post",
"content": "Post content here",
"published": true
}

Nested Serializers

class CommentSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.username', read_only=True)
class Meta:
model = Comment
fields = ['id', 'text', 'author', 'author_name', 'created_at']
class PostSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True, read_only=True, source='comment_set')
comment_count = serializers.SerializerMethodField()
class Meta:
model = Post
fields = ['id', 'title', 'content', 'comments', 'comment_count']
def get_comment_count(self, obj):
return obj.comment_set.count()

Best Practices

  • Versioning: Use API versioning (/api/v1/)
  • Pagination: Always paginate list endpoints
  • Error Handling: Return consistent error responses
  • Validation: Use serializer validation methods
  • Documentation: Use drf-yasg or drf-spectacular
  • CORS: Configure django-cors-headers for frontend
  • Throttling: Implement rate limiting
  • Testing: Write API tests using APITestCase
Security: Always use HTTPS in production!

Next Session: React & State Management

  • Introduction to React
  • Components, props, and state
  • React Hooks (useState, useEffect)
  • Fetching data from Django API
  • State management basics
  • Redux fundamentals

Preparation: Install Node.js and create-react-app

Questions & Discussion

Contact: JWilliams@Staff.newman.ac.uk

Office Hours: By appointment

Resources: DRF Documentation, Postman Learning Center

Thank you for your attention!