您的当前位置:首页正文

【DRF】Django Rest Framework(2.DRF概念以及APIView源码分析)

2024-11-26 来源:个人技术集锦

一、Django Rest Framework 概念

1. 解释

  • Django Rest Framework组件是Django的一个app或者应用
  • Rest 是基于 Restful的风格
  • Framework框架

2. 概念

二、djangorestframework安装

pip命令

pip install djangorestframework

三、DRF的APIView视图

1. 首先写个类视图并导入

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView


class BookView(APIView):

    def get(self, request):
        return HttpResponse("GET请求。。。。")

    def post(self, request):
        return HttpResponse("POST请求。。。。")

    def delete(self, request):
        return HttpResponse("delete请求。。。。")

2. APIView的源码 并解释

通过源码发现,APIView在as_view()函数里面,只是在最后的使用CSRF做了一层包装
那通过上篇博客,我们分析 类视图 的源码发现,一个请求,基本就是如下步骤和流程
get 请求访问/book/ => view() 相当于访问了这个view()函数 => dispatch() => return get()
post 请求访问/book/ => view() 相当于访问了这个view()函数 => dispatch() => return post()
既然在view中没有做多大改变,
那么重写的意义以及为什么要重新写个APIView类继承一下,就在dispatch()函数中

class APIView(View):
    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

    # Allow dependency injection of other settings to make testing easier.
    settings = api_settings

    schema = DefaultSchema()

    @classmethod
    def as_view(cls, **initkwargs):
        """
        Store the original class on the view function.

        This allows us to discover information about the view when we do URL
        reverse lookups.  Used for breadcrumb generation.
        """
        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的as_view方法,得到view()函数
        # 这块可以看我上篇博客里面 分析 类视图源码 就清晰了
        view = super().as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs

        # Note: session based authentication is explicitly CSRF validated,
        # all other authentication is CSRF exempt.
        return csrf_exempt(view)

3. dispatch()函数源码解释

APIView重写的dispatch()就是,进行封装一层认证、权限、限流的三件套
还有就是 新的 request对象

class APIView(View):
    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

    # Allow dependency injection of other settings to make testing easier.
    settings = api_settings

    schema = DefaultSchema()

    @classmethod
    def as_view(cls, **initkwargs):
        # ......这块省略
        pass

    # Note: Views are made CSRF exempt from within `as_view` as to prevent
    # accidental removal of this exemption in cases where `dispatch` needs to
    # be overridden.
    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传递最新的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

三、APIView 与 View 的区别

  • Request对象不同, 传入到视图方法中的是 REST Framework 的 Request 对象,
    而不是 Django 的HttpRequest对象

  • 视图方法可以返回 REST Framework 的 Request 对象,视图会为响应数据设置(render) 符合前端期望要求的格式

  • 任何 APIException 异常都会被捕获到,并且处理合适格式的响应信息返回给客户端

  • 重新声明了一个新的as_views方法并在dispatch()进行路由分发前,会对请求的客户端进行身份认证、权限检查、流量控制。

四、常用属性

1. request.data

request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和request.FILES属性,但提供了以下特性:

  • 包含了解析之后的文件和非文件数据
  • 包含了对POST、PUT、PATCH请求方式解析后的数据
  • 利用了REST Framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
2. request.query_params

request.query_params 与 Djangobiao标准的request.GET相同,正式更换了更为标准的名称

3. request._request

获取django封装的Request对象

显示全文