3月7日学习内容整理:restframework的解析器组件
首先我们要知道django中request.POST中要想有值,必须满足两个条件:
1、数据类型也就是content-type字段必须是application/x-www-form-urlencoded,如果不是,就要去request.body中去取
2、数据格式必须满足:x=1&d=2&f=33 这样的形式
restframeworkwork的解析器组件就是用来将浏览器发过来的数据,对于不同的数据类型有不同的解析器去处理封装这些数据,最后返回给视图直接拿来用就可以了
1、基本使用:
对于解析器,我们一般也不去自定义解析类,用rest内置类就够了
针对不同类型的数据我们调用不同的解析器就可以了
2、配置文件中设置全局使用
REST_FRAMEWORK = { # 设置全局的解析器,列表,里面依然存放解析器的路径 "DEFAULT_PARSER_CLASSES": ['rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser'] }
3、内置解析器:都在下面这个路径找
JSONParser是用来解析json数据的
FormParser是用来解析urlencoded数据的
注意一点:在配置文件中设置的话如果只设置一种解析器,那么也就只能解析一种类型的数据,别的类型就无法解析
from rest_framework.parsers import JSONParser,FormParser
4、源码流程
(1)首先在dispatch方法中,重新封装request对象中会把全局设置的解析器循环并且实例化对象,把这些对象保存在列表中封装到request对象中,到这一步就封装好了,只等到视图中调用request.data要取数据了,才会触发解析器分析数据
def initialize_request(self, request, *args, **kwargs): return Request( request, # 这个request是原生的request # 这个方法就得到了全局设置的解析器类的实例对象 parsers=self.get_parsers(), ) def get_parsers(self): return [parser() for parser in self.parser_classes]
(2)视图中执行request.data,也就是调用Request类中的data方法,data中调用request的_load_data_and_files方法,其中又调用_parse方法,_parse方法中的self.content_type就是指的数据的类型,就是请求头中的content_type值,继续执行self.negotiator.select_parser方法,这个方法就是根据请求的content_type值和解析器默认支持的content_type值做匹配,筛选出正确的解析器并返回,继续执行_parse方法,就会调用筛选出来的解析器(这里以JSONPaser解析器为例)的parse方法,parse方法就会获取到请求体,对请求体的数据进行解析,返回json反序列化的数据
@property def data(self): if not _hasattr(self, '_full_data'): self._load_data_and_files() return self._full_data
self._data, self._files = self._parse()
# content_type就是数据类型 media_type = self.content_type
# parses就是设置的解析器 parser = self.negotiator.select_parser(self, self.parsers)
parsed = parser.parse(stream, media_type, self.parser_context)
def select_parser(self, request, parsers): for parser in parsers: # media_type就是解析器类中支持的content-type值,根据支持的类型和 # 请求的类型筛选出正确的解析器,并返回 if media_type_matches(parser.media_type, request.content_type): return parser return None
def parse(self, stream, media_type=None, parser_context=None): parser_context = parser_context or {} encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) try: # 获取请求体,并解析 decoded_stream = codecs.getreader(encoding)(stream) parse_constant = json.strict_constant if self.strict else None # 返回反序列化的数据 return json.load(decoded_stream, parse_constant=parse_constant)
5、补充其它的内置解析器
(1)上传文件解析器:FileUploadParser
如果只是上传文件,可以在自定义view类中定义parser_classes=[FileUploadParser] 这样去写
这个解析器就是专门用来解析上传文件数据的,我们去文件的话就从request.FILES中取