drf框架的解析器和内容协商

一般来说,现在传输的数据形式主要是json,但是也包括form,file形式,那么我们看看在drf框架中如何接受这些数据。

python 复制代码
from django.shortcuts import render
from rest_framework.utils.urls import replace_query_param
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import QueryParameterVersioning, BaseVersioning,URLPathVersioning,AcceptHeaderVersioning
from rest_framework import exceptions
from rest_framework.parsers import JSONParser,FormParser,FileUploadParser,MultiPartParser
from rest_framework.negotiation import DefaultContentNegotiation

# Create your views here.
class HomeView(APIView):
 
    parser_classes =[MultiPartParser]
    content_negotiation_class =DefaultContentNegotiation
    def post(self,request,*args,**kwargs):
        # self.dispatch
        print(request.data)
        file_object=request.data.get('img')
        with open(file_object.name,mode='wb')as target_file_object:
            for chunk in file_object:
                target_file_object.write(chunk)
            file_object.close()
        return Response('请求成功')

我们来看看这个解析器,JSONParser,FormParser,FileUploadParser,MultiPartParser,这四个解析器,分别处理json,form,文件,文件加数据这四种类型,大概得原理是找到这个content-type是什么类型,然后根据DefaultContentNegotiation,来获得处理后的数据 大概的原理:

python 复制代码
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

进入dispatch函数,第8行,我们进去

python 复制代码
def initialize_request(self, request, *args, **kwargs):
    """
    Returns the initial request object.
    """
    parser_context = self.get_parser_context(request)

    return Request(
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )

这里面封装了parsers,content_negotiator,这里的parser_context获得的是调用这个函数的对象,以及传入的数据,这也为后面解析数据埋下伏笔,这个时候,他并没有进行任何的数据处理,当我们调用request.data的时候,才会进行数据的处理,我们进入封装的request的data方法看看

python 复制代码
@property
def data(self):
    if not _hasattr(self, '_full_data'):
        self._load_data_and_files()
    return self._full_data

从里面的大概意思上来看,就是如果这里面有数据了,那么就直接返回,如果还没有数据,那么就自行加载数据,感兴趣的可以细看这里面的流程,这里就不细说了。 我们可以依次来接受想要的数据,根据自己选择数据类型,他默认的parsers也可以根据self.parsers来查看,当然也可以在全局中进行配置,这些和前面的认证组件的原理都类似,这里就不再赘述。

相关推荐
摆烂工程师1 小时前
教你如何认证 Gemini 教育优惠的二次验证,薅个 1年的 Gemini Pro 会员
后端·程序员·gemini
绝无仅有1 小时前
未来教育行业的 Go 服务开发解决方案与实践
后端·面试·github
程序员爱钓鱼2 小时前
Go语言实战案例- 命令行参数解析器
后端·google·go
心在飞扬2 小时前
Redis 介绍与 Node.js 使用教程
后端
milanyangbo2 小时前
“卧槽,系统又崩了!”——别慌,这也许是你看过最通俗易懂的分布式入门
分布式·后端·云原生·架构
AAA修煤气灶刘哥3 小时前
MySQL 查文本查哭了?来唠唠 ES 这货:从 “啥是 ES” 到 Java 撸代码,一篇整明白!
java·后端·elasticsearch
金銀銅鐵3 小时前
[Java] 浅析密封类(Sealed Classes) 在 class 文件中是如何实现的
java·后端
007php0073 小时前
Go语言面试:传值与传引用的区别及选择指南
java·开发语言·后端·算法·面试·golang·xcode
唐叔在学习3 小时前
从MD5到RSA,一文读懂常见的加密算法
后端
javadaydayup3 小时前
为什么 MyBatis Mapper 接口能像普通 Bean 一样被 @Autowired?
后端·mybatis