drf—-5 view extension classes/9 view subclasses/view sets/drf routing

5 view extension classes

# Write 5 classes (not called view classes, view extension classes, need to be used together with GenericAPIView), each class has a method, which interface you want to write in the future, just inherit which class
from rest_framework.response import Response

##### We packaged it ourselves

# class ListModelMixin:
# def list(self, request, *args, **kwargs):
# qs = self. get_queryset()
# ser = self. get_serializer(qs, many=True)
# return Response({'code': 100, 'msg': 'success', 'results': ser.data})
#
#
# class CreateModelMixin:
# def create(self, request, *args, **kwargs):
# ser = self. get_serializer(data=request. data)
# if ser.is_valid():
# ser. save()
# return Response({'code': 100, 'msg': 'success'})
# else:
# return Response({'code': 100, 'msg': ser. errors})
#
#
# class RetrieveModelMixin:
# def retrieve(self, request, *args, **kwargs):
# book = self. get_object()
# ser = self. get_serializer(book)
# return Response({'code': 100, 'msg': 'success', 'results': ser.data})
#
#
## DestroyModelMixin, UpdateModelMixin
# class DestroyModelMixin:
# def destroy(self, request, *args, **kwargs):
# self. get_object(). delete()
# return Response({'code': 100, 'msg': 'Deleted successfully'})
#
#
# class UpdateModelMixin:
# def update(self, request, *args, **kwargs):
# book = self. get_object()
# ser = self. get_serializer(data=request. data, instance=book)
# if ser.is_valid():
# ser. save()
# return Response({'code': 100, 'msg': 'Update successful'})
# else:
# return Response({'code': 100, 'msg': ser. errors})


from .models import Book
from .serializer import BookSerialzier
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView

from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, \
    RetrieveModelMixin


class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerialzier

    def get(self, request):
        return self. list(request)

    def post(self, request):
        return self.create(request)



class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerialzier

    def get(self, request, *args, **kwargs):
        return self. retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self. update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

9 view subclasses

#ModelViewSet:
- After inheriting it, you only need to write two lines in your view class
    queryset = Book.objects.all()
    serializer_class = BookSerialzier
    -Configure routing, 5 interfaces are available
    path('books/', BookView. as_view({'get': 'list', 'post': 'create'})),
    path('books/<int:pk>/', BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
        
        
        
# ModelViewSet source code analysis
\t-inherit:      
    mixins.CreateModelMixin,
             mixins. RetrieveModelMixin,
             mixins.UpdateModelMixin,
             mixins.DestroyModelMixin,
             mixins.ListModelMixin
             GenericViewSet
                -ViewSetMixin: not seen, rewrite as_view
                -GenericAPIView
                
                
     -As long as the ModelViewSet is inherited, the way of routing changes, who controls it changes: ViewSetMixin
   

# How does ViewSetMixin control the route writing method to change?
-BookView.as_view is executing, it is actually ViewSetMixin's as_view
        @classonlymethod
        def as_view(cls, actions=None, **initkwargs):
            #The actions we pass in={'get': 'list', 'post': 'create'}
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                for method, action in actions.items():
                    # method: get
                    # action: list
                    # Through reflection, self is the object of BookView, take the reflection list in the BookView object
                    handler = getattr(self, action)
                    # Through reflection: setattr(BookView object, 'get', list method)
                    setattr(self, method, handler)
                # APIViwe's dispatch
                return self. dispatch(request, *args, **kwargs)
            return csrf_exempt(view)
\t
    
    
# Summarize:
'''
1 As long as ViewSetMixin and its subclasses are inherited, the routing method will change, and the actions parameter must be passed
2 becomes a mapping relationship:
path('books/', BookView. as_view({'get': 'list', 'post': 'create'})),
    3 Afterwards, as long as the books route is successfully matched, the get request will execute the list method of the view class BookView
    
    4 The method name in the view class in the future can be named arbitrarily
    5 This class must be used in conjunction with the view class (APIView, GenericAPIView, 9 view subclasses), and must be placed before the view class
'''

Viewset

Summary

# two view base classes
-APIView
    -GenericAPIView
# 5 view extension classes (not view classes, need to be used with GenericAPIView and its subclasses)
\t
# 9 view subclasses

# Viewset:
ModelViewSet: 5 interfaces
    ReadOnlyModelViewSet: two interfaces, list and retrieve
    ViewSetMixin: magic, cannot be used alone, must be used in conjunction with the view class, the routing method has changed
    ViewSet: ViewSetMixin + APIView, I want to inherit APIView in the future, but I want to change the routing method, and the methods in the view class can be named arbitrarily
    GenericViewSet: ViewSetMixin + GenericAPIView, I want to inherit GenericAPIView in the future, but I want to change the routing method, and the methods in the view class can be named arbitrarily

routing of drf

# There are many ways to write routes
- original writing
    -Writing of mapping: path('books/', BookView.as_view({'get': 'list', 'post': 'create'}))
    - Automatically generate routes
    
# Automatically generate routes
- You must inherit the view class of ViewSetMixin and its subclasses to use
    - Inherited 5 view extension classes + view class of ViewSetMixin, which can automatically generate routes
    - it's the same as what we wrote
         -path('books/', BookView. as_view({'get': 'list', 'post': 'create'})),
   -path('books/<int:pk>/', BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
        
        
    - How to map the method of the view class written by myself
    -mapped the way we would
        - the way of automatic generation
    \t
        
        
        
# Automatically generate routes
1 Inherited 5 view extension classes + view classes of ViewSetMixin, which can automatically generate routes (get:list,get:retrieve..)
    2 We named it ourselves: Method name: login send_sms, need to use decorator to do it
        # View class:
        class SMSView(ViewSet):
            @action(methods=['GET'], detail=False, url_path='lqz', url_name='lqz')
            def lqz(self, request):
        # routing
        router.register('lqz',SMSView,'lqz')
        # The path is: http://127.0.0.1:8000/api/v1/lqz/lqz/
        
   3 parameters of the action decorator
methods: request method
    detail: one True, one False, use True to indicate the path to generate details <int:pk>
    # True, books/1/methodname/
        # False, books/methodname/
    url_path: the path name, which needs to be added with the previous path, if not added, the function name is used as the path name by default
    url_name: the name used for reverse parsing (not used much)
    
    
    
    
 # Routing class, there are two, the usage is exactly the same, the difference is that DefaultRouter generates more paths
SimpleRouter: the most used
    DefaultRouter
    # The difference between DefaultRouter and SimpleRouter is that DefaultRouter will come with a default API root view and return a hyperlink response data containing all list views.