6.1 ViewSets
ViewSet classes are almost the same thing as View classes, except that they provide operations
such as retrieve, or update, and not method handlers
such as get or put.
In other word 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 operations/actions
such as .list() and .create().
Doc: https://www.django-rest-framework.org/api-guide/viewsets/
View CODE here: https://github.com/amrit94/drf-test/commit/45f6813f67bbf664f2a844b49b903dbf2c14dc83
# Types
* viewsets.ViewSet
* viewsets.ModelViewSet
* viewsets.ReadOnlyModelViewSet
* GenericViewSet
* Custom ViewSet base classes
urls.py
- If using ViewSet in views –> then create
action a/c to views-method
- If using ModelViewsSet in views –> then
all action
will work - If using ReadOnlyModelViewSet in views –>
list and retrieve
# snippets/urls.py
snippet_list = SnippetViewSet.as_view({
'get': 'list',
'post': 'create'
})
snippet_detail = SnippetViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
urlpatterns = format_suffix_patterns([
path('snippet/', snippet_list, name='snippet-list'),
path('snippet/<int:pk>/', snippet_detail, name='snippet-detail'),
])
6.1.1 viewsets.ViewSet
- Does not provide any actions by default -
No action
- So, if using ViewSet in views –> then create
action a/c to views-method
- The ViewSet class
inherits from APIView
It has no direct advantage
over APIView,
But if used along with routers, then URLs are auto created.
i.e The API URLs are now determined automatically by the router
.
# snippets/views.py
class SnippetViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Snippet.objects.all()
serializer = SnippetSerializer(queryset, many=True)
return Response(serializer.data)
6.1.2 viewsets.ModelViewSet
- Automatically
provides all actions
- create(), retrieve(), update(), partial_update(), destroy(), list()
- The ModelViewSet class
inherits from GenericAPIView
# snippets/views.py
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
6.1.3 ReadOnlyModelViewSet
- Automatically provides
list and retrieve
actions. - The ReadOnlyModelViewSet class also
inherits from GenericAPIView
# snippets/views.py
class SnippetViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
6.1.4 GenericViewSet
- The GenericViewSet class
does not provide any actions
by default,- but does include the base set of generic view behavior, such as
- the
get_object
andget_queryset
methods.
- The GenericViewSet class inherits from GenericAPIView
6.2 Routers
Because we’re using ViewSet classes rather than View classes, we actually don't need to design the URL
conf ourselves.
URLS can be handled automatically, using a Router class
# Steps
1st --> Create a Router
2nd --> Register router with appropriate viewset
Doc: https://www.django-rest-framework.org/api-guide/routers/
Types
- SimpleRouter
- No default API root
- DefaultRouter
- This router is similar to SimpleRouter as above, but
- Additionally
includes a default API root view
, - Or can create own API-root-view
- by using
@api_view
- views.py and urls.py
- by using
snippets/urls.py
- See
URL patterns naming
- Check url.py
# Create Roouter
router = routers.SimpleRouter()
# Register
router.register(r'snippets', SnippetViewSet)
# The API URLs are now determined automatically by the router.
urlpatterns = [
path('', include(router.urls)),
]
snippets/views.py
- We can use any of the
viewset
according to requirement - Check Code Here
Trade-offs between views vs viewsets
Using viewsets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf.
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.