drf源码剖析----解析器

点击查看代码
class HomeView(APIView):
# 规定传入的数据可以用JSON格式和Form格式
    parser_classes = [JSONParser, FormParser]
# 根据请求头选择解析器,寻找渲染器
    content_negotiation_class = DefaultContentNegotiation

    def post(self, request, *args, **kwargs):
        print(request.data, type(request.data)) #调用request.data开始使用解析器
        return Response('...')
点击查看代码
class APIView(View):

    def dispatch(self, request, *args, **kwargs):
        # url中的参数
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)

    def initial(self, request, *args, **kwargs):
        self.format_kwarg = self.get_format_suffix(**kwargs)

        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)

    def initialize_request(self, request, *args, **kwargs):
        parser_context = self.get_parser_context(request)

        return Request(
            request,      # django的request
            parsers=self.get_parsers(),   # 解析器的类对象
            authenticators=self.get_authenticators(),  # 认证类对象
            # DefaultContentNegotiation
            negotiator=self.get_content_negotiator(), 
            parser_context=parser_context # 视图对象和url参数
        )

    def get_parsers(self):
        return [parser() for parser in self.parser_classes]

    def get_content_negotiator(self):
        if not getattr(self, '_negotiator', None):
            self._negotiator = self.content_negotiation_class()
        return self._negotiator

    def get_parser_context(self, http_request):
        return {
            'view': self,
            'args': getattr(self, 'args', ()),
            'kwargs': getattr(self, 'kwargs', {})
        }
点击查看代码
class Request:

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        assert isinstance(request, HttpRequest), (
            'The `request` argument must be an instance of '
            '`django.http.HttpRequest`, not `{}.{}`.'
            .format(request.__class__.__module__, request.__class__.__name__)
        )

        self._request = request
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        self.negotiator = negotiator or self._default_negotiator()
        self.parser_context = parser_context
        self._data = Empty
        self._files = Empty
        self._full_data = Empty
        self._content_type = Empty
        self._stream = Empty

        if self.parser_context is None:
            self.parser_context = {}
        self.parser_context['request'] = self  # drf的request、encoding
        self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET

    @property
    def data(self):
        if not _hasattr(self, '_full_data'):
            self._load_data_and_files()
        return self._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

            if is_form_media_type(self.content_type):
                self._request._post = self.POST
                self._request._files = self.FILES

    def _parse(self):
        # 获取请求头content_type
        media_type = self.content_type
        # 请求发过来的原始数据
        stream = self.stream
        # 获取解析器 [JSONParser, FormParser]
        parser = self.negotiator.select_parser(self, self.parsers)
        # 解析 json.loads('{'v1':123}')/json.load(文件对象)
        parsed = parser.parse(stream, media_type, self.parser_context)

        try:
            return (parsed.data, parsed.files)
        except AttributeError:
            empty_files = MultiValueDict()
            return (parsed, empty_files)

posted @   周亚彪  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示