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中取

posted @ 2018-03-07 17:25  九二零  阅读(118)  评论(0编辑  收藏  举报