• cbv请求分析


    CBV源码分析

    DRF中中所有视图都是基于CBV形式完成, 所以分析其cbv源码, 了解drf的基本请求流程就比较有必要了.

    urls.py
    """下面是一个通用的url路由""""
    url(r'^books/$', views.Book.as_view())
    
    """as_view同样是drf视图类的入口"""
    
    views.py
    """下面是一个通用的简单的基于drf的apiview的一个视图"""
    class Book(APIView):
        def get(self, request, *args, **kwargs):
            # 这个接口提供两个接口来进行调用, 所以需要分开来进行判断
            # 判断路由中是否包含pk
            pk = kwargs.get('pk')
            # pk有值, 代表是查单本书
            if pk:
                try:
                    book = models.Book.objects.get(pk=pk, is_delete=False)
                except models.Book.DoesNotExist:
                    return Response({
                        'status': 1,
                        'msg': '图书不存在'
                    })
                ser_data = serializers.BookModelSerializer(book).data
            # 当没有查询单本书时, 即pk不存在的话, 默认进行查询所有图书
            else:
                books = models.Book.objects.filter(is_delete=False)  # 要找没有被删除的书籍
                ser_data = serializers.BookModelSerializer(books, many=True).data  # 不要忘记添加many=True的条件, 序列化多个对象对象
            return Response({
                'status': 0,
                'msg': '查询成功',
                'result': ser_data
            })
    

    as_view入口分析

    首先drf的apiview是继承自django中View, 并重写了as_view方法, 也就相当于改写了入口方法.

    	@classmethod
        def as_view(cls, **initkwargs):
            view = super().as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
    		# 直接禁用了csrf认证, 所以我们的post请求可以不携带csrftoken参数了.
            return csrf_exempt(view)
    

    上面是APIView的as_view方法, 重写的内容很简单, 只是将csrf认证禁用了, 并进行了一些参数的初始化工作. 接下来是重点, as_view方法调用了父类的as_view方法, 返回的结果才是url匹配后真正执行的内容, 也就是调用了dispatch方法来分发.

    dispatch分析

    """django的View的as_view方法"""
    @classonlymethod
        def as_view(cls, **initkwargs):
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get
                self.request = request
                self.args = args
                self.kwargs = kwargs
                # 视图类调用的方法.
                return self.dispatch(request, *args, **kwargs)
            view.view_class = cls
            view.view_initkwargs = initkwargs
            update_wrapper(view, cls, updated=())
            update_wrapper(view, cls.dispatch, assigned=())
            return view
    

    上面的源码部分清晰的看出了, 最后我们的路由匹配成功后, 最后走的是as_view内层的view方法, 也就是说调用了view类的dispatch方法, 而APIView正式重写了这个dispatch方法, 在这里做了许多的事, 因此可以说, dispatch才是drf中APIView的真正入口函数.

        def dispatch(self, request, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs
            # 重新封装了request对象
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                # 这里做了各种初始化工作, 包括频率,认证, 权限等的校验.
                self.initial(request, *args, **kwargs)
                # 和django中的一样, 需要符合对应的8种http请求方法, 才能正确走到对应的视图函数进行处理.
                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
    
  • 相关阅读:
    Java 中几种常用的线程池
    阿里巴巴java工程师面试经验详情
    设计模式-备忘录模式
    设计模式-职责链模式
    设计模式-中介者模式
    设计模式-解释器模式
    设计模式-观察者模式
    设计模式-迭代器模式
    设计模式-命令模式
    设计模式-模板方法模式
  • 原文地址:https://www.cnblogs.com/yscl/p/11930762.html
Copyright © 2020-2023  润新知