I have been looking everywhere to find a decent explanation for this, and they all come short...When do you use the @api_view decorator rather than a class based view with the django rest framework app
APIView. APIView class is a subclass of a Django View class. APIView classes are different from regular View classes in the following ways: Requests passed will be REST framework's Request instances, not Django's HttpRequest instances. Handler methods may return REST framework, instead of Django's HttpResponse.
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.
Django views facilitate processing the HTTP requests and providing HTTP responses. On receiving an HTTP request, Django creates an HttpRequest instance, and it is passed as the first argument to the view function. This instance contains HTTP verbs such as GET, POST, PUT, PATCH, or DELETE.
Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
REST Framework aside, it's the same question of when to use class based views versus function based views in general. CBVs in Django are awesome, flexible and save loads of boilerplate code, but sometimes it's just faster, easier and clearer to use a function based view. Think about it with the same approach you'd take to writing a normal view in Django. REST Framework simply supports both methods of writing view code as it introduces in the tutorial.
Generally go with a CBV unless it's getting in your way, then keep it simple with a function based view and the decorator. In both Django and the REST Framework, the logic for typical things like lists, pagination and CRUD operations is already written and easily extendable in the form of classes and mixins. If your view logic is doing something notably different, a function based view might be appropriate. And of course you can use both approaches in your app.
Personally, I use the APIView Base Class or @api_view decorator only when I need to do something very specific/custom. For example, to show a list of URLS of the endpoint, aggregate data from different models in a particular manner and so on.
Whenever I deal with usual list, create, update and delete operations I use the other classes (Retrieve, Create, Update and Destroy Views or Mixins).
Example of use of @api_view decorator to make a list of all the endpoints of my app:
from django.core.urlresolvers import NoReverseMatch
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from .urls import urlpatterns
@api_view(('GET',))
def root_endpoint(request, format=None):
"""
List of all the available resources of this RESTful API.
"""
endpoints = []
# loop over url modules
for urlmodule in urlpatterns:
# is it a urlconf module?
try:
urlmodule.urlconf_module
is_urlconf_module = True
except AttributeError:
is_urlconf_module = False
# if url is really a urlmodule
if is_urlconf_module:
# loop over urls of that module
for url in urlmodule.urlconf_module.urlpatterns:
# TODO: configurable skip url in settings
# skip api-docs url
if url.name in ['django.swagger.resources.view']:
continue
# try adding url to list of urls to show
try:
endpoints.append({
'name': url.name.replace('api_', ''),
'url': reverse(url.name, request=request, format=format)
})
# urls of object details will fail silently (eg: /nodes/<slug>/)
except NoReverseMatch:
pass
return Response(endpoints)
This code is on github.
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