In Django, the choice of how to create views

In Django, the choice of how to create views depends on the complexity of your application, the functionality you need, and your preferred level of abstraction. Below is a detailed comparison of the primary approaches—@api_view decorator, Generic Views, and ViewSets—with examples and situations where each is suitable:

1. @api_view Decorator (Function-Based Views)

What it is:

  • Provided by Django REST Framework (DRF).
  • A decorator to create simple function-based API views that can handle specific HTTP methods like GET, POST, etc.

When to Use:

  • For simple or small APIs.
  • When you need full control over the request-response cycle.
  • When you’re handling a single resource and don’t want to use DRF’s abstraction layers.

Example:





from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET', 'POST'])
def product_list(request):
    
    if request.method == 'GET':
        products = Product.objects.all()
        data = [ { 'title': product.title, 'price': product.price, 'id': product.id } for product in products]
        return Response(data)
        
    
    elif request.method == "POST":
        data = request.data ## dictionary 
        
        if data:
          new_product = Product.objects.create(**data)
          
        return Response({"id": new_product.id, "message":"Sucessfully created"})
        
        

Pros:

  • Simple and straightforward for small APIs.
  • Easy to understand and debug.
  • Full control over the logic.

Cons:

  • It can become repetitive and verbose for larger projects.
  • Lacks reusability and scalability compared to class-based views.

2. Generic Views (Class-Based Views)

What it is:

  • DRF’s pre-built class-based views for common patterns like listing, creating, retrieving, updating, and deleting objects.

When to Use:

  • When you want to save development time and use DRF’s built-in behavior.
  • For CRUD operations on resources.
  • When you want a good balance between customization and DRF abstraction.
from rest_framework.generics import ListCreateView, RetrieveUpdateDestoryAPIView
from .models import Product
from .serilizers impor ProductSerilizer

class ListProducts(ListCreateView):

    queryset = Product.objects.all()
    serializer_class = ProductSerilizer
    
class PorductDetailedView(RetrieveUpdateDestoryAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    

URL mapping

from django.urls import path
from .view import ListProducts, PorductDetailedView

urlpatterns = [
  path('products', ListProducts.as_view(), name='product-list-create'),
  path('products/<int:pk>', PorductDetailedView.as_view(), name = 'product-detail-update-delete')
]

Pros:

  • Saves time by handling common patterns like GET, POST, PUT, and DELETE.
  • Built-in query optimizations and easy integration with serializers.
  • Easier to maintain for standard CRUD operations.

Cons:

  • Less flexible compared to function-based views.
  • Can become harder to debug if too much customization is needed.

3. ViewSets

What it is:

  • A higher-level abstraction provided by DRF that combines the logic for handling multiple HTTP methods (e.g., list, create, retrieve, etc.) into a single class.

When to Use:

  • For complex APIs where resources have multiple endpoints (e.g., /products/ and /products/<id>/).
  • When you want to utilize DRF’s Router to automatically generate URL routes.
  • For APIs that benefit from adhering to RESTful standards.

Example:

from rest_framework.viewsets import ModelViewSet
from .models import Product
from .serializers import ProductSerializer

class ProductViewSet(ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerialize

Routing Example:

from rest_framework.routers import DefaultRouter
from .views import ProductViewSet

router = DefaultRouter()
router.register(r'products', ProductViewSet, basename='product')

urlpatterns = [
    # Other URLs
] + router.urls

Pros:

  • Simplifies API development by managing routing automatically.
  • Great for adhering to RESTful design principles.
  • Combines functionality for multiple HTTP methods in a single class.

Cons:

  • Requires more understanding of DRF abstractions.
  • Overkill for very simple APIs.

When to Choose Each

ApproachWhen to Use
@api_view– Small, simple APIs.
– Full control over logic.
– Minimal abstractions are desired.
Generic Views– Standard CRUD operations.
– Moderate complexity.
– When you want to leverage DRF’s built-in behavior.
ViewSets– Large, complex APIs.
– RESTful endpoints with multiple HTTP methods.
– You want to use DRF’s routing system.

Summary Table

Feature@api_viewGeneric ViewsViewSets
Ease of UseSimpleModerateAdvanced
CustomizationHighModerateLow
Best ForSmall APIsCRUD operationsRESTful APIs with routing
RoutingManualManualAutomatic (with Router)
Abstraction LevelLowMediumHigh

Recommendation

  • Start with @api_view for learning or very simple APIs.
  • Use Generic Views for CRUD operations to save time and reduce code.
  • Opt for ViewSets when building larger, more complex APIs where you can take advantage of routers.

Leave a Reply

Your email address will not be published. Required fields are marked *

Deprecated: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/wp-includes/formatting.php on line 4720