rest-framework之解析器

目录

  • 一 解释器的作用
  • 二 全局使用解释器
  • 三 局部使用解释器
  • 四 源码分析

 一 解释器的作用

 

根据请求头 content-type 选择对应的解析器对请求体内容进行处理。

有application/json(json格式字符串),x-www-form-urlencoded,form-data(文件)等格式。

 

二 全局使用解释器

settings.py 配置文件中:

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':[
        'rest_framework.parsers.JSONParser'
        'rest_framework.parsers.FormParser'
        'rest_framework.parsers.MultiPartParser'
    ]

}

 

路由中:

urlpatterns = [
    url(r'test/', TestView.as_view()),
]

 

视图函数中:

from rest_framework.views import APIView
from rest_framework.response import Response

class TestView(APIView):
    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

 

三 局部使用解析器

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser,FormParser, MultiPartParser



class TestView(APIView):
    parser_classes = [JSONParser, ]
    #在这里填入可以被解析的类型,
    #如果全局与局部都设置了解析器,那么以局部的为准

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)

        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

注意:局部和全局都有解释器时,以局部设置的解释器为准。

 

四 源码分析

 

#在调用request.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._data, self._files = self._parse()

        def _parse(self):
            #用户请求头里content_type的值
            media_type = self.content_type

            #self.parsers 就是用户配置的parser_classes = [FileUploadParser,FormParser ]
            #self里就有content_type,传入此函数
            parser = self.negotiator.select_parser(self, self.parsers)
#查看self.negotiator.select_parser(self, self.parsers)
     def select_parser(self, request, parsers):
        #同过media_type和request.content_type比较,来返回解析器,然后调用解析器的解析方法
        #每个解析器都有media_type = 'multipart/form-data'属性
        for parser in parsers:
            if media_type_matches(parser.media_type, request.content_type):
                return parser
        return None
#最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)

 

 

#Request实例化,parsers=self.get_parsers()
    Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
#get_parsers方法,循环实例化出self.parser_classes中类对象
    def get_parsers(self):
        return [parser() for parser in self.parser_classes]            
#self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
#api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,找不到,会到getattr方法
        def __getattr__(self, attr):
            if attr not in self.defaults:
                raise AttributeError("Invalid API setting: '%s'" % attr)

            try:
                #调用self.user_settings方法,返回一个字典,字典再取attr属性
                val = self.user_settings[attr]
            except KeyError:
                # Fall back to defaults
                val = self.defaults[attr]

            # Coerce import strings into classes
            if attr in self.import_strings:
                val = perform_import(val, attr)

            # Cache the result
            self._cached_attrs.add(attr)
            setattr(self, attr, val)
            return val
#user_settings方法 ,通过反射去setting配置文件里找REST_FRAMEWORK属性,找不到,返回空字典
    @property
    def user_settings(self):
        if not hasattr(self, '_user_settings'):
            self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
        return self._user_settings

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值