• REST-framework快速构建API--源码解析


    一、APIView

    通过APIView实现API的过程如下:

    urls.py

       url(r'^books/$', views.BookView.as_view(),name="books"),
        url(r'^books/(d+)/$', views.BookDetailView.as_view(),name="detailbook"),
    

    views.py

    class BookView(APIView):
        def get(self, request):
            book_list = Book.objects.all()
            bs = BookModelSerializers(book_list, many=True, context={'request': request})
            return Response(bs.data)
    
        def post(self, request):
            # post请求的数据
            bs = BookModelSerializers(data=request.data)
            if bs.is_valid():
                print(bs.validated_data)
                bs.save()  # create方法
                return Response(bs.data)
            else:
                return Response(bs.errors)
    
    
    class BookDetailView(APIView):
    
        def get(self, request, id):
    
            book = Book.objects.filter(pk=id).first()
            bs = BookModelSerializers(book, context={'request': request})
            return Response(bs.data)
    
        def put(self, request, id):
            book = Book.objects.filter(pk=id).first()
            bs = BookModelSerializers(book, data=request.data, context={'request': request})
            if bs.is_valid():
                bs.save()
                return Response(bs.data)
            else:
                return Response(bs.errors)
    
        def delete(self, request, id):
            Book.objects.filter(pk=id).delete()
    
            return Response()
    
    
    
    

    urls中,定义了两个url的请求方式:

    • 通过URL:http://127.0.0.1/books/   GET/POST数据

    • 通过URL:http://127.0.0.1/books/id/   GET/PUT/DELETE数据

    第一种,url(r'^books/$', views.BookView.as_view(),name="books"),调用过程如下:

    views.BookView.as_view()

      1、APIView.as_view(),返回view,实际上是执行View.as_view()

        2、View中的as_view()返回disptch()函数

          3、self会从View类往上找dispatch(),在APIView类中有找到dispatch()

            4、dispatch()会找get、post、put、delete等方法

              5、在当前View下,BookView类下定义了get、post,BookDetailView类下定义了get、put、delete

                6、执行当前类下的对应方法

    第二种URL执行过程一样。

    二、ModelView

    通过ModelView实现API过程如下:

    urls.py

     url(r'^authors/$', views.AuthorModelView.as_view({'get':'list','post':'create'}),name="authors"),
     url(r'^authors/$', views.AuthorModelView.as_view({'get':'retrieve','post':'update','delete':'destory'}),name="authors"),

    views.py

    class AuthorModelView(viewsets.ModelViewSet):
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
      

    执行过程如下:

    1、当前类下没有as_view方法,从父类ModelViewSet中查找

    
    
    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):
        """
        A viewset that provides default `create()`, `retrieve()`, `update()`,
        `partial_update()`, `destroy()` and `list()` actions.
        """
        pass
    
    
    

    2、ModeViewSet在mixins中没有as_view,从GenericViewSet往上找

    
    
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        """
        The GenericViewSet class does not provide any actions by default,
        but does include the base set of generic view behavior, such as
        the `get_object` and `get_queryset` methods.
        """
        pass
    
    
    

    3、从ViewSetMixin中找到了as_view(),实际上返回了dispatch()

    ViewSetMixin==>generics.GenericAPIView==>views.APIView==>dispatch()

    4、执行dispatch(),实际上是找get、post、put、delete等方法

    5、在当前类下找到对应的方法

     

     

    三、认证、权限、频率源码

     通过ModelView方式实现认证,

    局部应用:

    class AuthorModelView(viewsets.ModelViewSet):
    
        authentication_classes = [TokenAuth, ]
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
        pagination_class = StandardResultsSetPagination
    

      

      

    全局应用:

    REST_FRAMEWORK={
        "DEFAULT_AUTHENTICATION_CLASSES":["app01.utils.TokenAuth",],
     
    }
    

      

    源码实现过程:

    服务端以authors为例:

     1、在AuthorModelView中查找as_view(),在本类中找不到,往上查找;

     2、父类:viewsets.ModelViewSet

    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):
        """
        A viewset that provides default `create()`, `retrieve()`, `update()`,
        `partial_update()`, `destroy()` and `list()` actions.
        """
        pass
    

      3、其他几个父类没有as_view()和祖父类了,只能从GenericViewSet往上找;

    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        """
        The GenericViewSet class does not provide any actions by default,
        but does include the base set of generic view behavior, such as
        the `get_object` and `get_queryset` methods.
        """
        pass
    

      4、最左边父类ViewSetMixin查找as_view(),找到了

      5、ViewSetMixin中的as_veiw()实际上返回了dispatch()

      6、再查找dispatch()方法,顺序:generics.GenericAPIView==>APIView==>dispatch()

      

        def dispatch(self, request, *args, **kwargs):
            """
            `.dispatch()` is pretty much the same as Django's regular dispatch,
            but with extra hooks for startup, finalize, and exception handling.
            """
            self.args = args
            self.kwargs = kwargs
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                self.initial(request, *args, **kwargs)
    
                # Get the appropriate handler method
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
    
                response = handler(request, *args, **kwargs)
    
            except Exception as exc:
                response = self.handle_exception(exc)
    
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response
    

      7、dispatch()中,先会执行self.initial()

        def initial(self, request, *args, **kwargs):
            """
            Runs anything that needs to occur prior to calling the method handler.
            """
            self.format_kwarg = self.get_format_suffix(**kwargs)
    
            # Perform content negotiation and store the accepted info on the request
            neg = self.perform_content_negotiation(request)
            request.accepted_renderer, request.accepted_media_type = neg
    
            # Determine the API version, if versioning is in use.
            version, scheme = self.determine_version(request, *args, **kwargs)
            request.version, request.versioning_scheme = version, scheme
    
            # Ensure that the incoming request is permitted
            self.perform_authentication(request)
            self.check_permissions(request)
            self.check_throttles(request)
    

      8、initial()中会对过来的请求进行认证、授权、频率检测。

    图标流程如下:

      

  • 相关阅读:
    JSP的动态Include的静态Include
    JAVA观察者模式
    JAVA单例模式
    【转】 linux 安装nginx及编译参数详解
    【转】Linux下nginx配置https协议访问的方法
    【转】./configure && make && make install详解
    【转】linux下如何查看某个软件 是否安装?安装路径在哪
    【转发】查看Linux版本系统信息方法汇总
    【转发】CentOS 7 巨大变动之 systemd 取代 SysV的Init
    【转发】centos 7安装完后出现please make your choice from '1' ......
  • 原文地址:https://www.cnblogs.com/skyflask/p/10422335.html
Copyright © 2020-2023  润新知