• drf4 视图与路由组件


    APIView和View的区别

    不管是View还是APIView最开始调用的都是as_view()

    APIView继承了View, 并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。

     

    在View中的as_view方法返回了view函数,而view函数执行了self.dispatch()方法,但是这里的dispatch方法应该是我们APIView中的

    去initialize_request中看下把什么赋值给了request,并且赋值给了self.request, 也就是我们在视图中用的request.xxx到底是什么~~

    看到,这个方法返回的是Request这个类的实例对象~~我们注意我们看下这个Request类中的第一个参数request,是我们走我们django的时候的原来的request

    我们看到了,这个Request类把原来的request赋值给了self._request, 也就是说以后_request是我们老的request,新的request是我们这个Request类

    我们用了rest_framework框架以后,我们的request是重新封装的Request类

    request.query_params 存放的是我们get请求的参数

    request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求

    相比原来的django的request,我们现在的request更加精简,清晰了

    现在我们知道了APIView和View的一些区别

    视图的第一次封装

    GenericAPIView 是对 APIView 的封装 
    xxxMixin  是对处理的各种请求方法的封装
    
    
    class BookView(APIView):
    
        def get(self, request):
            query_set = Book.objects.all()
            book_ser = BookSerializer(query_set, many=True)
            return Response(book_ser.data)
    
        def post(self, request):
            query_set = request.data
            book_ser = BookSerializer(data=query_set)
            if book_ser.is_valid():
                book_ser.save()
                return Response(book_ser.validated_data)
            else:
                return Response(book_ser.errors)
    
    
    class BookEditView(APIView):
    
        def get(self, request, id):
            query_set = Book.objects.filter(id=id).first()
            book_ser = BookSerializer(query_set)
            return Response(book_ser.data)
    
        def patch(self, request, id):
            query_set = Book.objects.filter(id=id).first()
            book_ser = BookSerializer(query_set, data=request.data, partial=True)
            if book_ser.is_valid():
                book_ser.save()
                return Response(book_ser.validated_data)
            else:
                return Response(book_ser.errors)
    
        def delete(self, request, id):
            query_set = Book.objects.filter(id=id).first()
            if query_set:
                query_set.delete()
                return Response("")
            else:
                return Response("删除的书籍不存在")
    
    APIView视图
    APIView
    from rest_framework.views import APIView
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.response import Response
    from .serializers import BookSerializer
    
    
    
    
    class GenericAPIView(APIView):
        query_set = None
        serializer_class = None
    
        def get_queryset(self):
            return self.query_set
    
        def get_serializer(self, *args, **kwargs):
            return self.serializer_class(*args, **kwargs)
    
    
    class ListModelMixin(object):
        def list(self, request):
            queryset = self.get_queryset()
            ret = self.get_serializer(queryset, many=True)
            return Response(ret.data)
    
    
    class CreateModelMixin(object):
        def create(self, request):
            serializer = self.get_serializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)
            else:
                return Response(serializer.errors)
    
    
    class RetrieveModelMixin(object):
        def retrieve(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            ret = self.get_serializer(book_obj)
            return Response(ret.data)
    
    
    class UpdateModelMixin(object):
        def update(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            serializer = self.get_serializer(book_obj, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)
            else:
                return Response(serializer.errors)
    
    
    class DestroyModelMixin(object):
        def destroy(self, request, id):
            book_obj = self.get_queryset().filter(id=id).first()
            book_obj.delete()
            return Response("")
    
    
    class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        pass
    
    
    class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        pass
    
    
    # class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
    class BookView(ListCreateAPIView):
        query_set = Book.objects.all()      # 操作的表的对象
        serializer_class = BookSerializer   # 序列化的类
    
        def get(self, request):
            # book_obj = Book.objects.first()
            # ret = BookSerializer(book_obj)
            # book_list = Book.objects.all()
            # book_list = self.get_queryset()
            # ret = self.get_serializer(book_list, many=True)
            # return Response(ret.data)
            return self.list(request)
    
        def post(self, request):
            # print(request.data)
            # serializer = BookSerializer(data=request.data)
            # if serializer.is_valid():
            #     serializer.save()
            #     return Response(serializer.data)
            # else:
            #     return Response(serializer.errors)
            return self.create(request)
    
    
    # class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    class BookEditView(RetrieveUpdateDestroyAPIView):
        query_set = Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request, id):
            # book_obj = Book.objects.filter(id=id).first()
            # ret = BookSerializer(book_obj)
            # return Response(ret.data)
            return self.retrieve(request, id)
    
        def put(self, request, id):
            # book_obj = Book.objects.filter(id=id).first()
            # serializer = BookSerializer(book_obj, data=request.data, partial=True)
            # if serializer.is_valid():
            #     serializer.save()
            #     return Response(serializer.data)
            # else:
            #     return Response(serializer.errors)
            return self.update(request, id)
    
        def delete(self, request, id):
            # book_obj = Book.objects.filter(id=id).first()
            # book_obj.delete()
            # return Response("")
            return self.destroy(request, id)
    
    视图的第一次封装

    视图的第二次封装

    class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        pass
    
    class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        pass
    
    class BookView(ListCreateAPIView):
        pass
    
    class BookEditView(RetrieveUpdateDestroyAPIView):
        pass
    
    # 上面我们写的继承类太长了~~我们再改改
    
    class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        pass
    
    
    class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        pass
    
    
    class BookView(ListCreateAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
    
        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 BookEditView(RetrieveUpdateDestroyAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request, id, *args, **kwargs):
            return self.retrieve(request, id, *args, **kwargs)
    
        def patch(self, request, id, *args, **kwargs):
            return self.update(request, id, *args, **kwargs)
    
        def delete(self, request, id, *args, **kwargs):
            return self.delete(request, id, *args, **kwargs)
    
    第二次封装
    第二次封装

    视图的第三次封装

    ViewSetMixin

    actions这个默认参数其实就是我们路由可以进行传参了

    下面这个循环,可以看出,我们要传的参数是一个字段~key应该是我们的请求方式,value应该对应我们处理的方法

    这样我们每个视图就不用在写函数了,因为已经和内部实现的函数相对应了

    因为是按照请求的方式不同反回的结果,所有第二次有两个视图函数

    现在指定一个视图函数

      # 视图类传参,不同的请求对应不同的方法
        path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
        path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
    

    注意一点,用框架封装的视图,我们url上的那个关键字参数要用pk,系统默认的

    # class ViewSetMixin(object):
    #     def as_view(self):
    #         """
    #         按照我们参数指定的去匹配 对应的方法
    #         get-->list
    #         :return: 不用我们去写,框架有
    #         """

    ViewSetMixin 请求分发方法的原理,将不同的请求设置为不同的方法

    from rest_framework.viewsets import ViewSetMixin
    
    
    # class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
    #     queryset = Book.objects.all()
    #     serializer_class = BookSerializer
    
    
    # 如果我们再定义一个类
    class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
        pass
    
    
    class BookView(ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
    
    第三次封装
    第三次封装
    from rest_framework.viewsets import ViewSetMixin
    
    class ModelViewSet(ViewSetMixin, GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        pass
    
    # from rest_framework.viewsets import ModelViewSet
    #  框架内部已经实现了的,可以直接导入
    #
    class BookModelViewSet(ModelViewSet):
        
        query_set = Book.objects.all() 自己封装的query_set
      # queryset = Book.objects.all() # 框架的是queryset
    serializer_class = BookSerializer
    
    
    
    
    
    
    
    
    from rest_framework import views     # APIView
    from rest_framework import generics # GenericAPIView, 组合类
    from rest_framework import mixins #混合继承类
    from rest_framework import viewsets # ViewSetMixin 分发请求的类

    我们现在的视图就只要写两行就可以了

    image

    用框架的时

    路由为

     path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
    

    前面自己定义的是id,用框架时注意修改过来

     path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
    
     # 视图类传参.只有业务需求匹配性很强才用。通常情况下不这么用容易暴露接口
     # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
     # path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

    继承顺序

    DRF的路由

    from django.urls import path, include
    from .views import BookView, BookEditView, BookModelViewSet
    from rest_framework.routers import DefaultRouter
    
    
    router = DefaultRouter()
    
    router.register(r"", BookModelViewSet)  # 不能 加$ r"$"
    
    
    urlpatterns = [
        # path('list', BookView.as_view()),
        # path('retrieve/<int:id>', BookEditView.as_view()),
    
    
        # 视图类传参.只有业务需求匹配性很强才用。通常情况下不这么用容易暴露接口
        # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
        # path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
    
    ]
    
    
    urlpatterns += router.urls
    
    DefaultRouter
    DRF的路由

    通过框架我们可以把路由视图都变的非常简单,但是需要自定制的时候还是需要我们自己用APIView写

    当不需要那么多路由的时候,也不要用这种路由注册

    总之,一切按照业务需要去用

  • 相关阅读:
    如何在 Windows 7 上安装 TeX Live 2018
    CF 964C Alternating Sum
    WF 18 A 想法
    CLion 使用笔记
    数理统计学复习
    ssh无密码访问设置(ssh-keygen 的详解)
    mysql开启远程连接的方法
    mysql命令大全
    Linux下创建仓库的软件包createrepo
    Linux 格式化分区 报错Could not stat --- No such file or directory 和 partprobe 命令
  • 原文地址:https://www.cnblogs.com/wenyule/p/10434256.html
Copyright © 2020-2023  润新知