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 小时前
springboot 动态配置定时任务
java·spring boot·后端
计算机-秋大田2 小时前
基于SpringBoot的美食烹饪互动平台的设计与实现(源码+SQL脚本+LW+部署讲解等)
vue.js·spring boot·后端·课程设计·美食
加油,旭杏2 小时前
【go语言】grpc 快速入门
开发语言·后端·golang
brzhang2 小时前
墙裂推荐一个在 Apple Silicon 上创建和管理虚拟机的轻量级开源工具:lume
前端·后端
沈韶珺3 小时前
Visual Basic语言的云计算
开发语言·后端·golang
沈韶珺3 小时前
Perl语言的函数实现
开发语言·后端·golang
美味小鱼4 小时前
Rust 所有权特性详解
开发语言·后端·rust
我的K84094 小时前
Spring Boot基本项目结构
java·spring boot·后端
慕璃嫣5 小时前
Haskell语言的多线程编程
开发语言·后端·golang
晴空๓5 小时前
Spring Boot项目如何使用MyBatis实现分页查询
spring boot·后端·mybatis