DRF(2)APIView源码解析

文章目录

  • APIView简单使用
  • APIView源码解析
    • as_view被重写
    • dispatch 被重写

APIView简单使用

view


from rest_framework.views import APIView
from django.http import HttpResponse


class BookAPIView(APIView):
    def get(self, response):
        return HttpResponse("APIView GET")

    def post(self, response):
        return HttpResponse("APIView POST")

url

from django.urls import path
from . import views

urlpatterns = [
    path('apiview/', views.BookAPIView.as_view())
]

APIView源码解析

我们能发现,案例中和之前不一样的只有APIView是从rest_framework.view中拿到的而不是django

继承的类也变成了APIView,那么我们来看一下APIView中写了什么

class APIView(View):
    ...

首先看到就是他继承就是我们上一章讲的View,这说明他们的大致流程基本一致,那么做了什么改进呢?

as_view被重写

# 类方法装饰器
@classmethod
# 这里的cls依然是BookAPIView
def as_view(cls, **initkwargs):
    # BookAPIView中是否有 queryset 属性,并判断他是不是 QuerySet类型
    if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
        def force_evaluation():
            raise RuntimeError(
                'Do not evaluate the `.queryset` attribute directly, '
                'as the result will be cached and reused between requests. '
                'Use `.all()` or call `.get_queryset()` instead.'
            )

        cls.queryset._fetch_all = force_evaluation
    # 调用父类
    view = super().as_view(**initkwargs)
    view.cls = cls
    view.initkwargs = initkwargs

    # 不受到跨域影响
    return csrf_exempt(view)

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实例
    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
        # 这里传入的request是新的
        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

你可能感兴趣的:(#,DRF,django,python,后端)