• Django(49)drf解析模块源码分析


    前言

    上一篇分析了请求模块的源码,如下:

    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
        )
    

    上述源码中parsers=self.get_parsers()就是解析模块源码的入口
     

    源码分析

    我们点击get_parsers进入查看该方法

    def get_parsers(self):
        """
        Instantiates and returns the list of parsers that this view can use.
        """
        return [parser() for parser in self.parser_classes]
    

    该方法实例化并返回此视图可以使用的解析器列表,我们点击parser_classes,查看解析器列表

    api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
    
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    

    我们会发现解析器列表,是从api_settings中的DEFAULT_PARSER_CLASSES查找的,而api_settings又等于APISettings中的DEFAULTS,我们可以从settings中的DEFAUITS列表的DEFAULT_PARSER_CLASSES,如下:

    DEFAULTS = {
        # Base API policies
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer',
            'rest_framework.renderers.BrowsableAPIRenderer',
        ],
        'DEFAULT_PARSER_CLASSES': [
            'rest_framework.parsers.JSONParser',
            'rest_framework.parsers.FormParser',
            'rest_framework.parsers.MultiPartParser'
        ],
    }
    

    我们可以看到,drf默认的解析器列表中有3个解析器,这3个解析器中都有media_type属性,代表支持解析的数据提交类型

    • JSONParser:media_type = 'application/json'
    • FormParser:media_type = 'application/x-www-form-urlencoded'
    • MultiPartParser: media_type = 'multipart/form-data'

    如果我们想在以上3个解析器的基础上,再加上文件类型的解析器,那么需要全局配置。
     

    全局配置

    我们可以在settings.py文件中设置REST_FRAMEWORK配置,具体设置如下:

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

    这样,我们以后所有继承于APIView的类视图都可以解析上面配置的4种数据类型,但是如果我们想某个视图只能解析json格式的数据,那么就需要局部配置
     

    局部配置

    默认全局配置是因为我们写的视图继承自APIViewAPIView中配置了类属性parser_classes,所以我们自己编写的视图函数中,也设置个类属性,并且导入JSONParser解析器

    from rest_framework.parsers import JSONParser
    class TestView(APIView):
        # 局部解析类配置
        parser_classes = [JSONParser]
    
        def post(self, request, *args, **kwargs):
            print(request.data)
            return Response("drf post ok")
    

    接着我们使用application/x-www-form-urlencoded提交数据,会有如下报错

    {
        "detail": "不支持请求中的媒体类型 “application/x-www-form-urlencoded”。"
    }
    

    然后我们使用multipart/form-data提交数据,也会报错

    {
        "detail": "不支持请求中的媒体类型 “multipart/form-data; boundary=--------------------------022567055086460827891894”。"
    }
    

    最后我们使用application/json提交数据,响应成功

    "drf post ok"
    

    自定义解析器

    如果我们想自定义一个解析器,也很简单,默认的3个解析器都继承自BaseParser,我们查看下源码

    class BaseParser:
        """
        All parsers should extend `BaseParser`, specifying a `media_type`
        attribute, and overriding the `.parse()` method.
        """
        media_type = None
    
        def parse(self, stream, media_type=None, parser_context=None):
            """
            Given a stream to read from, return the parsed representation.
            Should return parsed data, or a `DataAndFiles` object consisting of the
            parsed data and files.
            """
            raise NotImplementedError(".parse() must be overridden.")
    

    如果我们需要自定义解析器,那么就必须继承自BaseParser,并且设置属性media_type,还要重写parse方法,有需求的小伙伴可以自行尝试,这里就不演示了

  • 相关阅读:
    关于桌面的图片打开很慢的解决方法
    用c#进行递归组合
    ajax,js,css 入门页面
    择日宣判此案,却常再无下文
    共享软件的明确定义
    [转]大逃亡,还没出来呢
    如何收集带有附件的网页
    送一份自家产的软件给园内的兄弟姐妹作“福利”
    [转]评蒙牛内幕
    蓝侠==la*uan,破解中国共享软件联盟著名灌水专家“蓝侠””
  • 原文地址:https://www.cnblogs.com/jiakecong/p/14859967.html
Copyright © 2020-2023  润新知