@api_view: It converts the function based view into a subclass of API view.
@renderer_classes: It takes an iterable set of renderer classes which helps in creating response to a request with various media types.
@parser_classes: It takes an iterable set of parser classes which allows REST to accept requests with different various media types.
@authentication_classes: It takes an iterable set of authentication classes that will allow REST authenticate the request.
@throttle_classes: It takes an iterable set of throttle classes that will limit number of requests per user in a specific amount of time.
@permission_classes: It takes an iterable set of permission classes that allows REST to check whether user allowed to take the requested resource or not.
@detail_route: It will mark the function/method to be served for detail request.
@list_route: It will mark the function/method to served for list request.
All other decorators must come after @api_view
Every decorator takes a single argument which must be a list or tuple of classes except @detail_route, @list_route.
We need to configure the urls for FBV views.
Generic Views(Class Based Views - CBV):
REST class based views are just like django class based views.
Every incoming request will be dispatched to the appropriate method handler just like django CBV.
APIView is the base class for all the DRF CBV and GenericAPIView is the base class for all the generic CBV.
Following are the generic views provided by the DRF
To customise default behaviour of the DRF by overriding the appropriate methods and attributes.
We need to configure the urls for CBV views.
To use CBV we must have basic understanding of Object Oriented Programming.
ViewSets:
ViewSets works exactly same as generic views(CBV). The only difference is that it allows us to combine the logic for set of related views in a single class.
It does not provide method handlers like "get", "post", "put", etc.
We do not configure the urls with ViewSets instead we use Routers to register viewsets.
Routers generates urls for ViewSets automatically and binds methods like "retrieve", "list", "create", "update", "delete", "partial_upate" for different request method types(GET, POST, etc).
DRF provides three generic viewsets GenericViewSet, ReadOnlyModelViewSet, ModelViewSet.
GenericViewSet:
It does not include the basic actions/methods like "list", "create", etc. we have to define these methods in order to use it.
But It provides methods like "get_object" and "get_queryset"
Inherit it and use it only if you want to implement completly new behaviour rather than the basic behaviour provided by DRF.
ReadOnlyModelViewSet:
It provides the functionality of CBV views ListAPIView and RetrieveAPIView in a single class.
It accepts only accepts the request method type "GET"
ModelViewSet:
It provides complete functionality of CBV of DRF in a single class.
You can avoid writing of six different classes.
You can also avoid configuring of urls for classes.
Examples: create user with django-rest-framework
# serializers.pyfrom django.contrib.auth.models import User
from rest_framework import serializers
classUserSerializer(serializers.ModelSerializer):
classMeta:
model = User
fields = ("first_name", "last_name", "email")
# function based views.pyfrom django.contrib.auth.models import User
from .serializers import UserSerializer
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
@api_view(['POST'])# other decorators if required@permission_classes([IsAuthenticated])defuser_create(request):
serializer = UserSerializer(data=request.POST)
if serializer.is_valid():
password = serializer.validated_data.get("password")
serializer.object.set_password(password)
serializer.save()
return Response({"message": "User Created"}, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors)
# function based urls.pyfrom django.conf.urls import url
from . import views
urlpatterns = [
url(r'^user-create/$', views.user_create, name="user-create"),
]
# generic views.pyfrom rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from .serializers import UserSerializer
classUserCreateView(generics.CreateAPIView):
serializer_class = UserSerializer
permission_classes = (IsAuthenticated, )
# generic urls.pyfrom django.conf.urls import url
from . import views
urlpatterns = [
url(r'^user-create/$', views.UserCreateView.as_view(), name="user-create"),
]
# viewsets.pyfrom rest_framework import viewsets
classUserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
permission_classes = (IsAuthenticated, )
# viewsets urls.pyfrom django.conf.urls import url, include
from rest_framework import routers
from . import viewsets
router = routers.DefaultRouter()
router.register(r'users', viewsets.UserViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
]
If you observe the above example code you can absorve that we have to write complete code inorder to get the full functionality even if it is a common case. But where as in generic views we can avoid the writing of repetitive code for common cases. In both the generic views and function based views we configured the urls with views. But, In viewsets we registered the ViewSet class with register. The advantage of register is that it can generate the urls & binds the appropriate methods to different request method types. If you are dealing with large project more number of views and url configurations. It will make maintenace of project difficult. By using Routers and ViewSets we can better maintain the project though it deals with a little abstraction.