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.