The introduction

Official document: http://www.django-rest-framework.org/ DRF provides us with powerful general view functions, this blog on these views for a brief summary analysis. First, let’s take a look at the main types of Views and their relationships.

Mixins are also involved, which are mainly divided into five categories: Let’s take the course as an example to summarize the view.

1. django View

First, we use Django’s built-in View to get a list of lessons:

# DRF is a json format for data interaction, so json data is also returned here
import json
from django.views.generic.base import View
from django.core import serializers
from django.http import HttpResponse,JsonResponse
from .models import Course

class CourseListView(View):
    def get(self, request):
        """Implementing the course List page with Django's View"""
        courses = Course.objects.all()[:10]
        json_data = serializers.serialize('json', Courses)
        json_data = json.loads(json_data)
        return JsonResponse(json_data, safe=False)
Copy the code

2. APIView

Next, we use the APIView to implement

from rest_framework.views import APIView
from rest_framework.response import Response
Serializers are custom defined in other files, so we won't go into too much about them here
from .serializers import CourseSerializer

class CourseListView(APIView):
    def get(self, request, format=None):
        """Implement course list page through APIView"""
        courses = Course.objects.all()
        serializer = CourseSerializer(courses, many=True)
        return Response(serializer.data)
Copy the code

In the APIView example, the serializer and Response methods of DRF are called. The APIView encapsulates Django’s own views.From the above code, the differences don’t seem that great, but in reality the APIView does a lot. It defines properties and methods, to name a few

These three are common attributesAuthentication_classes: user login authentication mode, session, token, etc. Permission_classes: permission Settings, whether login is required or not throttle_classes: Speed limit Settings, the user to a certain number of access limits and so on.Copy the code

This may not be enough to show the power of DRF through Views, but the GenericAPIView shows how powerful it is.

3. GenericAPIView

from rest_framework import mixins
from rest_framework import generics
class CourseListView(mixins.ListModelMixin, generics.GenericAPIView):
	"""Course List Page"""
 	queryset = Course.objects.all()
 	serialize_class = CourseSerializer
 	def get(self, request, *args, **kwargs):
 	The # list method is in mixins, as is create, etc
 	# GenericAPIView does not have these methods!
 		return self.list(request, *args, **kwargs)
Copy the code

In this example, we inherit the ListModelMixin from mixins, and in the get() method, we call its list() method, which returns json data from querySet. Mixins are not covered too much here. GenericAPIView encapsulates APIView again to achieve powerful functions:

  • Add the QuerySet attribute, which can be set directly without passing the instantiated courses to Seriliazer, and the system will automatically detect it. In addition, you can overload get_querySet () so you don’t have to set ‘QuerySet =*’, which makes it more flexible and allows for full customization.
  • Add the serializer_class attribute and implement the get_serializer_class() method. One or the other is enough, so you don’t have to specify a serilizer when you return
  • Set the filter template: filter_backends
  • Set the paging template: pagination_class
  • The addition of lookup_field=” PK “and the implementation of the get_object method: this is rarely used, but important. They have the same relationship as 1, either setting the property or overloading the method. Their function is to specify what suffix is passed in when an instance is retrieved. For example, for a specific course, the assumption of the incoming ulr is: http://127.0.0.1:8000/course/1/, the system will default this 1 refers to the course id. So, now I have a problem. Suppose I define a user’s favorite model, and I want to know if my course with ID 1 is favorites. The URL I pass in is: http://127.0.0.1:8000/userfav/1/, the system will default to obtain userfav instance id = 1, this logic is clearly wrong, we need to obtain the course id = 1 collection records, So we either need to use this property or override the method lookup_field=”course_id”. Generics includes several other views in addition to GenericAPIView: CreateAPIView, ListAPIView, RetrieveAPIView, ListCreateAPIView, etc. They all just inherit one or more mixins and GenericapiViews. What good is that? Let’s look at the code for the same example:
class CourseListView(ListAPIView):
	"""Course List Page"""
 	queryset = Course.objects.all()
 	serialize_class = CourseSerializer
Copy the code

This completes exactly the same function as just now!

4.GenericViewSet

  • Shortcomings of GenericAPIView

GenericAPIView and its related views already do a lot of things, so why bother with ViewSet? First of all, let’s think about a problem. In the same example above, we need to get a list of courses, and we also need to get specific information about a course. So how to implement, according to GenericAPIView, we can implement:

Class CourseView(ListAPIView, RetrieveAPIView): #   You just need to inherit RetrieveAPIView from above. queryset = Course.objects.all() serialize_class = CourseSerializerCopy the code

There is a problem with serialize_class. Obviously, when retrieving the course list, we only need to return the brief information about all the courses, such as the course name, the teacher, the cover, etc. But when retrieving the course details, we also need to return their chapters and related downloads (obviously, Chapter is another model with a foreign key pointing to course), this information will be a lot, and it is obviously not sensible to pass it back after retrieving the list of courses. You’ll also need to define a CourseDetailSerializer for get /courses/ and CourseDetailSerializer for get /courses/ ID /. So, the question is, how do we find out which action method it is? At this point, the viewset comes in!

  • GenericViewSet inherits GenericAPIView, still has get_querySet,get_serialize_class attributes and methods, GenericViewSet overwrites the as_view method, You can get the HTTP request method. To solve the problem:
from rest_framework import viewsets
import...
class CourseViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
 	queryset = Course.objects.all()
 	
	def get_serializer_class(self):
	# override get_serializer_class
	    if self.action == 'list':
	        return CourseSerializer
	    return CourseDetailSerializer

Copy the code
  • The HTTP request method is bound to the mixins method but GenericViewSet itself still doesn’t exist the list create method, we need to mix it with mixins, so what’s the new problem? Do we still need to write get, post, return list, or create methods ourselves? Of course not! Overriding the as_view method gives us the ability to bind when we set the URL:
# bind
courses = CourseViewSet.as_view({
	'get': 'list'.'post': 'create'
})
urlpatterns = [
	...
	Add url matches in general
	url(r'courses/', CourseViewSet.as_view(), name='courses'),]
Copy the code

Thus, we associate the HTTP request method with the mixins method. So what’s a cleaner way to do it? Obviously, there is, and that’s where Route comes in!

  • Route method registration and binding
from rest_framework.routers import DefaultRouter
router = DefaultRouter() You only need to implement it once
router.register(r'courses', CourseViewSet, base_name='courses')
urlpatterns = [
	...
	You only need to join once
	url(rA '^', include(router.urls)),]
Copy the code

The route must be ViewSet. Registering urls with router.register method can not only manage urls well, but also realize the connection between HTTP methods and relevant methods in mixins. In viewSets, there are also two mixins-bound viewsets, which can be implemented by themselves:

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    Satisfy the situation where only the GET method is requested
    pass
    
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    # Fulfill all requests
    pass
Copy the code

Here, the powerful function of ViewSet is introduced, strongly suggest that when doing DRF, the use of ViewSet and mixins method combined with development, for me this kind of white developers to provide a very powerful complete function!

After the speech

The author will summarize mixins and so on. I am also a beginner. If there is something wrong, please point out and discuss it.