Loading... ## 先总结: drf的核心是ModelViewSet类的演变, 所以懂了它基本上drf就可以毕业了 1. APIView (继承Django的View) * 去除csrf, 数据放到.data中, 执行三大认证 🆑🆑🆑🆑第二层🆑🆑🆑🆑 2. GenericAPIView(继承APIView) * 封装orm的instance 与 serializer 到属性中, 以方法形式供调用 🆑🆑🆑🆑第三层🆑🆑🆑🆑 3. 引入 xxxModelMixin * 封装*每个执行过程* 到list/create/update/retrieve/destroy方法属性中 * ListModelMixin * CreateModelMixin * UpdateModelMixin * RetrieveModelMixin * DestroyModelMixin ```python # 直接执行对应方法即可 class BooksGenericAPIView(GenericAPIView, ListModelMixin, CreateModelMixin,): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) ``` 🆑🆑🆑🆑第四层🆑🆑🆑🆑 4. 整个2与3成为 xxxAPIView (继承2, 组合继承3中任意几个) * *进一步将get/post/put/delete方法封装并实现*, *无需实现get..等方法* * 提供上面5个基础接口类+4个组合接口类 共 9个 ```五个基础接口类 CreateAPIView = GenericAPIView + CreateModelMixin DestroyAPIView = GenericAPIView + DestroyModelMixin ListAPIView = GenericAPIView + ListModelMixin UpdateAPIView = GenericAPIView + UpdateModelMixin RetrieveAPIView = GenericAPIView + RetrieveModelMixin ``` ```4个组合接口类 (继承原理同上) ListCreateAPIView RetrieveUpdateAPIView RetrieveDestroyAPIView RetrieveUpdateDestroyAPIView ``` ```python from rest_framework.generics import CreateAPIView,ListAPIView,\ DestroyAPIView,UpdateAPIView,RetrieveAPIView,\ ListCreateAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView, \ RetrieveUpdateDestroyAPIView # get/put/delete class BookGetPutDeleteAPIView(RetrieveUpdateDestroyAPIView): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer # get/post class BookGetsPostAPIView(ListCreateAPIView): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer ``` 🆑🆑🆑🆑第五层🆑🆑🆑🆑 引入ViewSetMixin (重写as_view), ViewSet(继承APIView, ViewSetMixin) * 让get/post/等http请求在view里与actions(create/update…)进行映射 dispatch时直接执行self.actions方法 引入GenericViewSet(继承ViewSetMixin, GenericAPIView) * as_view可以映射请求 * 封装了instance/serializer 5. ModelViewSet (继承上两个, 同时再继承xxModelMixin) * xxModelMixin提供self.actions方法, * ViewSetMixin 一一作了映射, * GenericAPIView 对instance/serializer作了封装 > 最终实现 -> *一个类实现5个接口且无需写任何方法* ## 上完整代码 ```python # 终极写法: (仅适用于ORM操作数据库) from rest_framework.viewsets import ModelViewSet from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView class BookModelViewSet(ModelViewSet): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer ``` ``` ''' =========第一层: 使用APIView========== ''' from rest_framework.generics import GenericAPIView from rest_framework import status class BookGenericAPIView(views.APIView): def get(self, request, *args, **kwargs): obj_list = models.Book.objects.all() ser = serializers.BookModelSerializer(instance=obj_list, many=True) return response.Response(ser.data, status=status.HTTP_200_OK) def post(self, request, *args, **kwargs): ser = serializers.BookModelSerializer(data=request.data) if ser.is_valid(): ser.save() return response.Response(data=ser.data, status=status.HTTP_200_OK) else: return response.Response(data=ser.errors, status=status.HTTP_400_BAD_REQUEST) def put(self, request, *args, **kwargs): obj = models.Book.objects.filter(pk=kwargs.get('id')).first() ser = serializers.BookModelSerializer(instance=obj, data=request.data) if ser.is_valid(): ser.save() return response.Response(data=ser.data, status=status.HTTP_200_OK) else: return response.Response(data=ser.errors, status=status.HTTP_406_NOT_ACCEPTABLE) def delete(self, request, *args, **kwargs): obj = models.Book.objects.filter(pk=kwargs.get('id')).delete() if obj: return response.Response(data='删除成功', status=status.HTTP_200_OK) else: return response.Response(data='不存在', status=status.HTTP_200_OK) ''' =========第二层: 无需定义对象与序列化器 ========================= 使用GenericAPIView(它继承自APIView) =========GenericAPIView把instance和serializer进行封装============= ''' from rest_framework.generics import GenericAPIView from rest_framework import status class BooksGenericAPIView(GenericAPIView): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer # 查多条 def get(self, request, *args, **kwargs): obj_list = self.get_queryset() ser = self.get_serializer(instance=obj_list, many=True) return response.Response(ser.data, status=status.HTTP_200_OK) # 增一条 def post(self, request, *args, **kwargs): print(request.data) ser = self.get_serializer(data=request.data) if ser.is_valid(): ser.save() return response.Response(data=ser.data, status=status.HTTP_200_OK) else: return response.Response(data=ser.errors, status=status.HTTP_400_BAD_REQUEST) class BookGenericAPIView(GenericAPIView): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer # 查一条 def get(self, request, *args, **kwargs): obj = self.get_object() ser = self.get_serializer(instance=obj) return response.Response(data=ser.data, status=status.HTTP_200_OK) # 改一条 def put(self, request, *args, **kwargs): obj = self.get_object() ser = self.get_serializer(instance=obj, data=request.data) if ser.is_valid(): ser.save() return response.Response(data=ser.data, status=status.HTTP_200_OK) else: return response.Response(data=ser.errors, status=status.HTTP_406_NOT_ACCEPTABLE) # 删一条 def delete(self, request, *args, **kwargs): obj = self.get_object().delete() if obj: return response.Response(data='删除成功', status=status.HTTP_200_OK) else: return response.Response(data='不存在', status=status.HTTP_200_OK) ''' =========第三层: 无需写执行步骤 + (需要写get/post..方法) ============ 使用GenericAPIView的同时集成xxxModelMixin(List/Create/..) 在对象和序列化器被GenericAPIView包装的基础上 ===============ModelMixin把第二层中的执行步骤进行封装================ ''' from rest_framework.generics import GenericAPIView from rest_framework.mixins import \ ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin class BooksGenericAPIView(GenericAPIView, ListModelMixin, CreateModelMixin,): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class BookGenericAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer 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) ''' ==================第四层: 无需写get/post..方法 =================== 把上面的类继续封装(属性封装+方法封装) + 内部实现get/post/put/delete方法 ================组合出9个xxxAPIView(同时继承Generic+xxModelMixin)============== CreateAPIView, DestroyAPIView, ListAPIView, UpdateAPIView, RetrieveAPIView ListCreateAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView RetrieveUpdateDestroyAPIView ''' from rest_framework.generics import CreateAPIView,ListAPIView,\ DestroyAPIView,UpdateAPIView,RetrieveAPIView,\ ListCreateAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView, \ RetrieveUpdateDestroyAPIView # get/put/delete class BookGetPutDeleteAPIView(RetrieveUpdateDestroyAPIView): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer # get/post class BookGetsPostAPIView(ListCreateAPIView): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer ''' =================第五层: 一个类实现5个接口 ==================== ViewSet -> ViewSetMixin + APIView | 映射 GenericViewSet -> ViewSetMixin + GenericAPIView | 映射 + 属性封装 ModelViewSet -> 5中ModelMixin + GenericViewSet | 映射 + 属性封装 + 方法封装并实现get/post等方法 =================对请求方式与执行方法映射的一层封装================ ViewSetMixin: 1.This is the magic. 2.APIView基础上重写as_view to create a concrete view binding the 'GET' and 'POST' methods to the 'list' and 'create' actions... view = BookViewSet.as_view({'get': 'list', 'post': 'create'}) ============================= ''' from rest_framework.viewsets import ViewSet,GenericViewSet, ModelViewSet from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView # 如下写法与第四层实现逻辑并无差别, 这就是第五层么? --不是! 第五层把下面两个类可以合二为一 class BookViewSet(RetrieveUpdateDestroyAPIView, ViewSet): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer class BooksViewSet(ListCreateAPIView, ViewSet): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer # 终极写法: (仅适用于ORM操作数据库) class BookModelViewSet(ModelViewSet): queryset = models.Book.objects serializer_class = serializers.BookModelSerializer ``` > 上图:  © 允许规范转载