Django Rest Framework — ViewSets vs Views for API development
Django Rest Framework (DRF) offers two main approaches for building APIs: ViewSets and Views. Both have their strengths and use cases…
Django Rest Framework (DRF) offers two main approaches for building APIs: ViewSets and Views. Both have their strengths and use cases. This article will explore the differences between these approaches, their benefits, and when to use each.
Before we dive in, I’d like to mention my book “Build RAG Applications with Django”. It covers Django fundamentals, RAG architectures, and AI integration. The book guides you through building selfGPT, a real-world RAG application that transforms your PDFs and text files into interactive AI insights. It includes practical examples of similarity search with pgvector, OpenAI API integration, and optimization techniques. As a bonus, you’ll receive the complete source code for selfGPT. Now, let’s explore Django Rest Framework!
Views in Django Rest Framework
Views in DRF are similar to traditional Django views but with added functionality for handling REST APIs. They’re class-based and derive from APIView.
Key characteristics of Views:
Granular control over HTTP methods
Explicit mapping of URLs to views
More flexibility for custom behavior
Here’s a simple example of a View in DRF:
from rest_framework.views import APIView
from rest_framework.response import Response
class UserView(APIView):
def get(self, request):
# Handle GET request
return Response({"message": "GET request processed"})
def post(self, request):
# Handle POST request
return Response({"message": "POST request processed"})ViewSets in Django Rest Framework
ViewSets are a higher-level abstraction over Views. They combine the logic for a set of related views in a single class.
Key characteristics of ViewSets:
Group related views into a single class
Automatically generate URL patterns
Provide default implementations for standard CRUD operations
Here’s an example of a ViewSet:
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializerComparing Views and ViewSets
Let’s break down the key differences:
1. Granularity:
Views offer fine-grained control over individual HTTP methods.
ViewSets group related actions together.
2. URL Routing:
Views require explicit URL mapping.
ViewSets can use routers for automatic URL generation.
3. Code Organization:
Views separate each HTTP method into its own function.
ViewSets combine related operations in a single class.
4. Default Implementations:
Views require you to implement each method explicitly.
ViewSets provide default implementations for common operations.
5. Customization:
Views allow for easier customization of individual actions.
ViewSets require overriding methods for custom behavior.
When to Use Views vs ViewSets
Use Views when:
You need fine-grained control over HTTP methods
Your API doesn’t follow standard CRUD patterns
You’re implementing custom actions that don’t fit into ViewSet conventions
Use ViewSets when:
Your API closely follows CRUD operations
You want to reduce boilerplate code
You’re working with a resource that has multiple related views
Real-World Example: ConnectorViewSet
Let’s examine a real-world example of a ViewSet from the provided code:
class ConnectorViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Connector.objects.all()
serializer_class = ConnectorSerializer
permission_classes = [IsAuthenticated]
lookup_field = "uuid"
def get_queryset(self):
return self.queryset.filter(user=self.request.user)
def list(self, request):
try:
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(api_response(result={"connectors": serializer.data}))
except Exception:
logger.exception("An unexpected error occurred while fetching connectors.")
return Response(
api_response(
success=False,
error="An unexpected error occurred while fetching connectors. "
"Please contact support at support@similarix.com.",
),
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
# ... other methods ...This ConnectorViewSet demonstrates several key features of ViewSets:
It inherits from
ReadOnlyModelViewSet, providing read-only operations.It defines a
querysetandserializer_class, which are used by the default implementations.It overrides
get_queryset()to filter results based on the current user.The
list()method is customized to handle exceptions and return a specific response format.
Advanced ViewSet Features
ViewSets offer several advanced features that can enhance your API development:
1. Custom Actions
You can add custom actions to ViewSets using the @action decorator:
from rest_framework.decorators import action
class ConnectorViewSet(viewsets.ReadOnlyModelViewSet):
# ... other code ...
@action(detail=True, methods=["post"])
def sync(self, request, uuid=None):
# Custom sync action implementation
passThis adds a POST /connectors/{uuid}/sync/ endpoint to your API.
2. Customizing Query Parameters
ViewSets allow you to customize how query parameters are handled:
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def get_queryset(self):
queryset = super().get_queryset()
username = self.request.query_params.get('username', None)
if username:
queryset = queryset.filter(username=username)
return queryset3. Nested ViewSets
For complex relationships, you can nest ViewSets:
from rest_framework_nested import routers
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
users_router = routers.NestedSimpleRouter(router, r'users', lookup='user')
users_router.register(r'accounts', AccountViewSet)
urlpatterns = [
path('', include(router.urls)),
path('', include(users_router.urls)),
]This creates URLs like /users/{user_pk}/accounts/.
Performance considerations
When working with ViewSets, keep these performance tips in mind:
Use
select_related()andprefetch_related()to optimize database queries.Implement pagination for large datasets.
Use caching for frequently accessed, rarely changing data.
The original and complete article is published at UnfoldAI blog: https://unfoldai.com/viewsets-views-drf/
Conclusion
Both Views and ViewSets have their place in Django Rest Framework development. Views offer more flexibility and control, while ViewSets provide a higher level of abstraction and reduce boilerplate code.
Choose Views when you need fine-grained control over HTTP methods or when implementing custom actions. Opt for ViewSets when working with standard CRUD operations or when you want to group related views together.
The best choice depends on your specific use case, API design, and development preferences. Don’t hesitate to mix both approaches in your project when it makes sense.
By understanding the strengths and use cases of both Views and ViewSets, you can create more efficient, maintainable, and scalable APIs with Django Rest Framework.
Thanks for reading; if you liked my content and want to support me, the best way is to —
Connect with me on LinkedIn and GitHub, where I keep sharing such free content to become more productive at building ML systems.
Follow me on X (Twitter) and Medium to get instant notifications for everything new.
Join my YouTube channel for upcoming insightful content.
Check my special content on my website;


