rest_framework(2)rest_framework.views.APIView 源码解析

本系列文章中的上一篇文章:CBV (基于类的视图)源码解析

关于 Content-Type 的知识补充

当 Content-Type = “urlencoded” 的时候,前端将会把参数以 urlencoded 的形式发送给后端,比如传递两个参数 a = 1, b = 2,那么将会变成 a=1&b=2 的形式

而当 Content-Type = “json” 的时候,前端将会把参数以  json 的形式发送给后端,比如传递两个参数 a = 1, b = 2,那么将会变成 {"a": 1, "b": 2} 的 json 形式

而 django 中原生的 request.POST 只能获取到 urlencoded 形式的参数,不能解析 json 格式的数据

urls.py 中的代码

from .views import BookView
urlpatterns = [
    path('book/', BookView.as_view()),
}

views.py 中 BookView 的代码

from rest_framework.views import APIView

class BookView(APIView):
    # 当前段发送 GET 请求时,会执行 get 方法,方法名为对应的请求类型,不能随便修改
    def get(self, request):
        return HttpResponse("APIView GET 请求....")

    # 当前段发送 POST 请求时,会执行 post 方法
    def post(self, request):
        return HttpResponse("APIView POST 请求...")

    # 当前段发送 DELETE 请求时,会执行 delete 方法
    def delete(self, request):
        return HttpResponse("APIView DELETE 请求....")

rest_framework.views.APIView 的源码(关键部分)

重写 django.views.View 中的 as_view() 方法

django.views.View 中的 as_view 的源码分析

@classmethod
def as_view(cls, **initkwargs):
    # ....

    # 调用 父类(View)中的 as_view
    # 故此处的 view 的逻辑和父类一样,此处的 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)

重写 django.views.View 中的 dispatch() 方法

dispatch 方法中新构建的 request ,可以通过 request.query_params 获取 get 请求中的参数,而 post 请求时数据通过 request.data 获取

无论前端以什么样的 Content-Type 发送数据,APIView 都会将其解析成 QueryDict 形式的字典(<QueryDict: {'a': ['100'] }>),做到了数据格式的统一

def dispatch(self, request, *args, **kwargs):
    # ....

    # 重新构建 request
    # 新构建的 request 解决了原生的 request.POST 只能解析 urlencoded 的不足
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?

    try:
        # 初始化:认证、权限、限流三件套
        self.initial(request, *args, **kwargs)

        # 分发逻辑,即根据不同的请求相应不同的请求方法
        # 此处的分发逻辑和父类中的 dispatch 差不多,可以参照上一篇文章
        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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值