Class-based Views

Keep our code DRY(Don’t repeat yourself).

One of the big wins of using class-based views is that it allows us to easily compose reusable bits of behaviour.

# Types
* APIview
* Mixins
* Generic

APIview

  • It looks pretty similar to the previous fxn based view,
  • but we’ve got better separation between the different HTTP methods
  • View CODE here
# views.py
from rest_framework.views import APIView

class SnippetList(APIView):
    def get(self, request, format=None):
    # this request is different from normal requst(used in fxn based)
    	...

class SnippetDetail(APIView):
    def get_object(self, pk)
    	...
    def get(self, request, pk, format=None):
    	...
# snippets/urls.py
urlpatterns = [
    path('snippets/', views.SnippetList.as_view()),
    path('snippets/<int:pk>/', views.SnippetDetail.as_view())
]

Mixins class based views

The mixin classes provide action methods(list, create) rather than defining the handler methods, such as .get() and .post(), directly

We’re then explicitly binding the get and post methods to the appropriate actions.

Doc: https://www.django-rest-framework.org/api-guide/generic-views/#mixins

# action methods - handler methods
list()     - get() - list_all
retrieve() - get() - list_one
create()   - post()
update()   - put()
destroy()  - delete()

View CODE here: https://github.com/amrit94/drf-test/blob/05-Mixin-Views/snippets/views.py

from rest_framework import mixins, generics

class SnippetList(mixins.ListModelMixin, mixins.CreateModelMixin,
          generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)      # list
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)    # create


class SnippetDetail(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,
          mixins.DestroyModelMixin, generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)  # retrive
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)    # update
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs    # destroy
  • queryset and serializer_class —> can’t modify their names

Generic class based views

Using the mixin classes we’ve rewritten the views to use slightly less code than before, but we can go one step further.

REST framework provides a set of already mixed-in generic views that we can use to trim down our views.py module even more.

Doc: https://www.django-rest-framework.org/api-guide/generic-views/#concrete-view-classes

from rest_framework import generics

class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer