DRF-解析器组件源码解析

解析器组件源码解析

解析器组件源码解析
1 执行request.data  开始找重装的request中的data方法
2     在dispatch找到重装的request
    def dispatch(self, request, *args, **kwargs):
        request = self.initialize_request(request, *args, **kwargs)
***这里开始找data
3 在initialize_request中找到实例request的类Request()
        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
        )
    得到类对象Request(),注意parsers=self.get_parsers()后面会回来找
4 Request()中找到data方法
5 在data方法中--关注返回值
    @property
    def data(self):
        if not _hasattr(self, '_full_data'):
            self._load_data_and_files()
        return self._full_data
    由于返回值默认:self._full_data = Empty
    所以self._load_data_and_files()应该对_full_data进行复制了
6 从_load_data_and_files()找到_full_data
        def _load_data_and_files(self):

            if not _hasattr(self, '_data'):
                self._data, self._files = self._parse()
                if self._files:
                    self._full_data = self._data.copy()
                    self._full_data.update(self._files)
                else:
                    self._full_data = self._data
    这里我们把self._parse()的结果分别复制给了self._data, self._files,且都放在了_full_data中,接下来观察self._parse()都给了什么值
7 _parse()
    def _parse():
        parser = self.negotiator.select_parser(self, self.parsers)
        parsed = parser.parse(stream, media_type, self.parser_context)
        empty_files = MultiValueDict()
        return (parsed, empty_files)
    parsed通过parser获取,而传入的参数中的self.parsers,就是我们初始化Request()中传入的参数parsers=self.get_parsers()

// *****这里开始开始和parser_classes我们的设置解析数据类型设置相关了    
8 我们回到步骤3找到parsers=self.get_parsers()
9 在get_parsers()中
    return [parser() for parser in self.parser_classes]
    得到从self.parser_classes中循环的列表
// *****选择从调用的视图类中获取parser_classes,没有从APIView中获取parser_classes
10 在APIView中获取到parser_classes
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
11 从api_settings查找DEFAULT_PARSER_CLASSES方法或属性
    api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
    @property
    def user_settings(self):
        if not hasattr(self, '_user_settings'):
            self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
        return self._user_settings
    class APISettings():
        def __init__(defaults=None):
            self.defaults = defaults or DEFAULTS 
            # 这里将DEFAULTS字典放在实例对象中,
        def __getattr__(self, attr):
            if attr not in self.defaults:
                raise AttributeError("Invalid API setting: '%s'" % attr)

            try:
                # Check if present in user settings
                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
    self.defaults = defaults or DEFAULTS --》这里将DEFAULTS字典放在实例对象中,我们发现DEFAULT_PARSER_CLASSES
    就在字典中
    由于没有DEFAULT_PARSER_CLASSES方法,我们执行__getattr__方法
        1***** val = self.user_settings[attr]优先从配置中找有没有配置的路由解析方法,如果没配置
        2***** val = self.defaults[attr]从实例化对象的内存空间中找方法
        3 val = perform_import(val, attr)将'rest_framework.parsers.JSONParser'转化成JSONParser

 解析器顺序

  当前访问视图类下------------》全局settings---------》默认default

使用

# 设置全局解析方式
REST_FRAMEWORK={
'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    ),
}

 

# 当前访问视图类下设置解析方式
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView

class LoginView(APIView):
    parser_classes = [JSONParser]
    def get(self,request):
        print('get')
        return render(request,'login.html')
    def post(self,request):
        print('body',request.body)
        print(request.data)
        print('data',request.data)
        # print('POST', request.POST)
        return HttpResponse('OK')
# 默认使用的解析方式
class APIView(View):
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES

 

posted @ 2018-09-18 17:16  神秘嘉宾7m  阅读(252)  评论(0编辑  收藏  举报