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 小时前
C# 关于多线程如何实现需要注意的问题(持续更新)
windows·后端·microsoft·c#·.net·.netcore·死锁
程序新视界2 小时前
为什么不建议基于Multi-Agent来构建Agent工程?
人工智能·后端·agent
Victor3562 小时前
Hibernate(29)什么是Hibernate的连接池?
后端
Victor3562 小时前
Hibernate(30)Hibernate的Named Query是什么?
后端
源代码•宸3 小时前
GoLang八股(Go语言基础)
开发语言·后端·golang·map·defer·recover·panic
czlczl200209253 小时前
OAuth 2.0 解析:后端开发者视角的原理与流程讲解
java·spring boot·后端
颜淡慕潇3 小时前
Spring Boot 3.3.x、3.4.x、3.5.x 深度对比与演进分析
java·后端·架构
布列瑟农的星空3 小时前
WebAssembly入门(一)——Emscripten
前端·后端
小突突突4 小时前
Spring框架中的单例bean是线程安全的吗?
java·后端·spring
iso少年4 小时前
Go 语言并发编程核心与用法
开发语言·后端·golang