I don't know why the documentation says:
That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function based views. Using viewsets is less explicit than building your views individually.
If I want to make a REST API (like in ruby-on-rail) I think viewsets
is a good approach to take.
Can anyone explain more about it?
While regular views act as handlers for HTTP methods, viewsets give you actions, like create or list . The great thing about viewsets is how they make your code consistent and save you from repetition. Every time you write views that should do more than one thing, a viewset is the thing that you want to go for.
APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.
APIView and ViewSet all have their right use cases. But most of the time, if you are only doing CRUD on resources, you can directly use ViewSets to respect the DRY principle. But if you are looking for more complex features, you can go low-level because after all, viewsets are also a subclass of APIView .
A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as . get() or . post() , and instead provides actions such as . list() and . create() .
The main advantage of using viewsets
over views
is brevity. In the simple case, you can get more done with fewer lines of code.
The main disadvantage is that the simplifying assumptions made by viewsets
might not always fit the problem space you are working in. As with class-based views in Django, if you try to apply the wrong pattern to a problem you can end up doing more work than you need to solve a problem.
My personal heuristic is that if I am doing the full set of CRUD operations on a model, I start with viewsets
and go from there until I feel the convenience they provide is no longer worth the trouble I am incurring in that specific instance; if I am working with an API endpoint that doesn't map to any models, I'm far more likely to just use a view
.
If I had the following models:
models.py
from django.db import models
class Gizmo(models.Model):
name = models.CharField(blank=True, null=False)
last_dusted = models.DateField(null=True)
class Sprocket(models.Model):
nom = models.CharField(blank=True, null=False)
last_dusted = models.DateField(null=True)
And I wanted to support the standard HTTP methods with their normal meanings, (namely GET and POST on the list view and GET, PUT, and DELETE on the detail view), I'd create a GizmoViewSet
, a SprocketViewSet
and call it a day.
Say I also wanted to offer API consumers the ability to dust off all of the gizmos at once. In that case, it would make sense to add a dust
method to the GizmoViewSet
using the @list_route
decorator. Suppose that what I really wanted to do though was to offer a single endpoint where that API consumer could dust all the Gizmo
s and the Sprocket
s off at once. That doesn't really map very well to either viewset, so I'd add a one off view:
import datetime
from rest_framework.decorators import api_view
from rest_framework.response import Response
from my_app.models import Gizmo, Sprocket
# I used a function-based API view here, but a CBV APIView
# would work just as well. Matter of personal preference...
@api_view
def dust_everything(request):
today = datetime.date.today()
Gizmo.objects.all().update(last_dusted=today)
Sprocket.objects.all().update(last_dusted=today)
return Response({"status_of_dusting": "successful"})
So in that case I wouldn't be tearing out all my viewsets and replacing them with views; I'm adding an extra view to supplement the existing viewsets where it makes sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With