drf-解析器(reqeust.data)
使用 request.data 获取请求体中的数据。
这个 reqeust.data 的数据怎么来的呢?其实在drf内部是由解析器,根据请求者传入的数据格式 + 请求头来进行处理。
from rest_framework.settings import api_settings
from rest_framework.negotiation import DefaultContentNegotiation
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser, FileUploadParser
class OrderView(APIView):
# 所有的解析器
# parser_classes = api_settings.DEFAULT_PARSER_CLASSES
parser_classes = [JSONParser, FormParser, MultiPartParser]
# 根据请求头,匹配对应的解析器;寻找渲染器
# content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
content_negotiation_class = DefaultContentNegotiation
def get(self, request, *args, **kwargs):
return Response('OK')
JSONParser (*)

FormParser

MultiPartParser(*)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
<input type="text" name="user" />
<input type="file" name="img">
<input type="submit" value="提交">
</form>
</body>
</html>
FileUploadParser(*)

解析器可以设置多个,默认解析器:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, JSONParser, FormParser
class UserView(APIView):
def post(self, request):
print(request.content_type)
print(request.data)
return Response("...")
源码分析()
①、请求进来,执行父类APIView类的dispatch方法
②、self.initialize.request这个方法是APIView这个类的方法,这个函数返回一个Request的实例对象。
- 第一行调用了一个
get_parser_context方法
def initialize_request(self, request, *args, **kwargs):
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
)
③、进入get_parser_context方法本质是返回了一个字典
- view:当前的视图对象
- URL传过来的参数
- parser_context={视图对象,URL路由参数}
def get_parser_context(self, http_request):
return {
'view': self,
'args': getattr(self, 'args', ()),
'kwargs': getattr(self, 'kwargs', {})
}
④、回到②中parsers=self.get_parsers获取所有解析器类的对象列表
def get_parsers(self):
return [parser() for parser in self.parser_classes]
⑤、回到②中negotiator=self.get_content_negotiator获取类的对象DefaultContentNegotiation()
def get_content_negotiator(self):
if not getattr(self, '_negotiator', None):
self._negotiator = self.content_negotiation_class()
return self._negotiator
⑥、这时候再进去Request看看接受了这些参数后做了些什么操作
- 将这几个参数接受到对象属性中
- 给
parser_context新增一个drf的request和encoding(编码)
⑦、回到dispatch,最终走到执行反射视图函数,只有在视图函数中调用request.data才会触发解析的动作(多次调用也只会解析一次)
- 反射取
_full_data的值,若没有则接卸加载到_full_data - 若反射取到有这个值,直接返回
_full_data的值
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
⑧、进入到self._load_data_and_files中,
- 就是将解析到的数据加载到
self._full_data中 - 主要看
_parse干了哪些事
