Django REST - Serializers, Viewsets, Routers

DjangoDjango REST FrameworkFree Lesson

Advertisement

Introduction

Django REST Framework (DRF) provides powerful tools for building RESTful APIs. This tutorial covers serializers, viewsets, routers, and authentication.

Serializers

# serializers.py
from rest_framework import serializers
from .models import Article, Author, Tag

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = ['id', 'name', 'slug']

class AuthorSerializer(serializers.ModelSerializer):
    books_count = serializers.SerializerMethodField()
    
    class Meta:
        model = Author
        fields = ['id', 'name', 'email', 'bio', 'books_count']
    
    def get_books_count(self, obj):
        return obj.books.count()

class ArticleSerializer(serializers.ModelSerializer):
    author = AuthorSerializer(read_only=True)
    author_id = serializers.IntegerField(write_only=True)
    tags = TagSerializer(many=True, read_only=True)
    tags_ids = serializers.ListField(
        child=serializers.IntegerField(),
        write_only=True
    )
    
    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'author', 'author_id', 
                 'tags', 'tags_ids', 'published', 'created_at']
        read_only_fields = ['created_at']
    
    def validate_title(self, value):
        if len(value) < 5:
            raise serializers.ValidationError('Title too short')
        return value

    def create(self, validated_data):
        tags_ids = validated_data.pop('tags_ids', [])
        article = Article.objects.create(**validated_data)
        article.tags.set(tags_ids)
        return article

Viewsets and Views

# views.py
from rest_framework import viewsets, generics, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from .models import Article, Author
from .serializers import ArticleSerializer, AuthorSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['title', 'content']
    ordering_fields = ['created_at', 'published']
    
    def get_queryset(self):
        return Article.objects.filter(author=self.request.user)
    
    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        article = self.get_object()
        article.published = True
        article.save()
        return Response({'status': 'published'})
    
    @action(detail=False, methods=['get'])
    def published(self, request):
        articles = self.queryset.filter(published=True)
        serializer = self.get_serializer(articles, many=True)
        return Response(serializer.data)

class AuthorListView(generics.ListCreateAPIView):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

Routers and URLs

# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet, AuthorListView

router = DefaultRouter()
router.register(r'articles', ArticleViewSet, basename='article')

urlpatterns = [
    path('', include(router.urls)),
    path('authors/', AuthorListView.as_view()),
]

Authentication

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

# permissions.py
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user or request.user.is_staff

Practice Problems

  1. Create a serializer that handles nested relationships with custom validation
  2. Implement a ViewSet with custom actions for bulk operations
  3. Add pagination to a list view
  4. Configure token-based authentication
  5. Create a custom permission class for role-based access

Advertisement

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement