Function-based views vs. class-based views

Introduction

Django Rest Framework (DRF) provides two main ways to define views: Function-based views (FBVs) and Class-based views (CBVs). Each approach has its own advantages and use cases. This tutorial will explain the differences between FBVs and CBVs, their pros and cons, and provide practical examples of how to use each.

Prerequisites

Before you start, ensure you have a DRF project set up. If not, please refer to our previous tutorial on setting up a DRF project.

Function-based Views (FBVs)

Definition

Function-based views are simple functions that take a web request and return a web response. They provide a straightforward way to define views in Django and DRF.

Example Use Case: Simple Book API

Let’s create a simple API to manage books using function-based views.

Step 1: Define the Model

# myapp/models.py

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    published_date = models.DateField()

    def __str__(self):
        return self.title

Step 2: Create a Serializer

# myapp/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']

Step 3: Define Function-based Views

# myapp/views.py

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Book
from .serializers import BookSerializer

@api_view(['GET', 'POST'])
def book_list(request):
    if request.method == 'GET':
        books = Book.objects.all()
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = BookSerializer(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)

@api_view(['GET', 'PUT', 'DELETE'])
def book_detail(request, pk):
    try:
        book = Book.objects.get(pk=pk)
    except Book.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = BookSerializer(book)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = BookSerializer(book, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Step 4: Configure URLs

# myapp/urls.py

from django.urls import path
from .views import book_list, book_detail

urlpatterns = [
    path('books/', book_list, name='book-list'),
    path('books/<int:pk>/', book_detail, name='book-detail'),
]

Pros and Cons of Function-based Views

Pros
  • Simplicity: Easy to understand and write.
  • Explicitness: Clearly shows the flow of data and logic.
Cons
  • Reusability: Limited reusability and harder to extend.
  • Scalability: Can become cumbersome for complex views with multiple HTTP methods.

Class-based Views (CBVs)

Definition

Class-based views use Python classes to encapsulate the view logic. They provide a more structured and reusable way to define views in Django and DRF.

Example Use Case: Simple Book API

Let’s create the same API to manage books using class-based views.

Step 1: Define the Model

Same as the FBV example above.

Step 2: Create a Serializer

Same as the FBV example above.

Step 3: Define Class-based Views

# myapp/views.py

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

class BookListCreate(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BookRetrieveUpdateDestroy(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

Step 4: Configure URLs

# myapp/urls.py

from django.urls import path
from .views import BookListCreate, BookRetrieveUpdateDestroy

urlpatterns = [
    path('books/', BookListCreate.as_view(), name='book-list'),
    path('books/<int:pk>/', BookRetrieveUpdateDestroy.as_view(), name='book-detail'),
]

Pros and Cons of Class-based Views

Pros
  • Reusability: Easy to extend and reuse code.
  • Scalability: Better suited for complex views with multiple HTTP methods.
  • Built-in Mixins: DRF provides mixins to handle common patterns, reducing boilerplate code.
Cons
  • Complexity: Slightly more complex to understand for beginners.
  • Less Explicit: The flow of logic can be less explicit compared to FBVs.

Conclusion

Both Function-based views and Class-based views have their place in Django Rest Framework. FBVs are great for simple, straightforward views, while CBVs provide a more structured and reusable approach for complex views. Understanding both approaches allows you to choose the best tool for the task at hand.


Tags: Function-based views vs. Class-based views in DRF, DRF views tutorial, how to use FBVs and CBVs in Django, Django API development