Django(49)drf解析模块源码分析[通俗易懂]

Django(49)drf解析模块源码分析[通俗易懂]前言上一篇分析了请求模块的源码,如下:definitialize_request(self,request,*args,**kwargs):"""Retu

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

前言

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

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方法,有需求的小伙伴可以自行尝试,这里就不演示了

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/166135.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 彻底解决mysql报错:1030, ‘Got error 28 from storage engine‘

    彻底解决mysql报错:1030, ‘Got error 28 from storage engine‘恕我直言,网上文章千篇一律,没一个能解决的,全是说清一下内存就好了,但是并没有教不会的小白清理…==这个问题确实是服务器系统盘满了,mysql指定的临时文件目录满掉,大概就是这个意思.下面解决/dev/vda1系统盘满了,其实我压根不知道/dev/vda1这在哪,是什么,后来了解这是virtio-block类型的设备。科普一下:以’c’开头的一行表示该设备是一个……

    2022年10月21日
    3
  • pandas之分组groupby()的使用整理与总结

    pandas之分组groupby()的使用整理与总结前言在使用pandas的时候,有些场景需要对数据内部进行分组处理,如一组全校学生成绩的数据,我们想通过班级进行分组,或者再对班级分组后的性别进行分组来进行分析,这时通过pandas下的groupby()函数就可以解决。在使用pandas进行数据分析时,groupby()函数将会是一个数据分析辅助的利器。groupby的作用可以参考超好用的pandas之groupby中作者的插图进行直…

    2022年5月9日
    47
  • matlab怎么将散点图的散点连线_plot函数画散点图

    matlab怎么将散点图的散点连线_plot函数画散点图1x=[2;4;8;10;12;16;18;20;22;25;26;30;40;46;48;66;68;70;82;84;100;110;120;130;140;150;160;170;180];

    2022年8月3日
    29
  • UNet详解(附图文和代码实现)

    卷积神经网络被大规模的应用在分类任务中,输出的结果是整个图像的类标签。但是UNet是像素级分类,输出的则是每个像素点的类别,且不同类别的像素会显示不同颜色,UNet常常用在生物医学图像上,而该任务中图片数据往往较少。所以,Ciresan等人训练了一个卷积神经网络,用滑动窗口提供像素的周围区域(patch)作为输入来预测每个像素的类标签。这个网络有两个优点:(1)输出结果可以定位出目标类别的位置;(2)由于输入的训练数据是patches,这样就相当于进行了数据增强,从而解决了生物医学图像数量少的问题。但是,

    2022年4月4日
    226
  • 双线性插值(超级易懂的)「建议收藏」

    双线性插值(超级易懂的)「建议收藏」双线性插值简介在两个方向分别进行一次线性插值(首先在一个方向上使用线性插值,然后再在另一个方向上使用线性插值执行双线性插值。尽管每个步骤在采样值和位置上都是线性的,但是插值总体上不是线性的,而是在采样位置上是二次的。)作用一般用于重新采样图像和纹理。计算四个周围纹理像素的属性(颜色,透明度等)的加权平均值,并将其应用于屏幕像素。(简单来说,我要求一个已知坐标的像素值,先去找他四个周围已…

    2022年4月28日
    207
  • python中求平均值(python调用自定义函数)

    该楼层疑似违规已被系统折叠隐藏此楼查看此楼defma(x,y):”’#自定义函数“ma(x,y)”指南函数格式:ma(x,y)函数功能:求序列数据x的y周期的简单平均值,输出值为序列平均值、即列表。函数使用举例:#输入:L=[1,2,3,4,5]ma(L,3)#输出:[2.0,3.0,4.0]#输出注解:(1+2+3)/3=2.0(2+3+4)/3=3.0(3+4+5)/3=4.0…

    2022年4月12日
    376

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号