• 解析器


    前提:django 的 request.POST 有值

    • 请求头要求:如果请求头中的 Content-Typeapplication/x-www-form-urlencoded ,才去 request.body 中解析数据
    • 数据格式要求:name=xi&age=18

    form 表单提交默认会按照上面的两种要求进行提交

    ajax 提交中的 data 数据虽然是字典格式,但默认也会把字典转换成上面的数据格式再带上请求头进行提交

    如果 ajax 提交中指定 headers 为 {'Content-Type': 'application/json'},那么 body 有值,POST 无值

    如果 ajax 提交中指定 headers 为 {'Content-Type': 'application/json'},且 data 的数据格式指定为 JSON.stringfy(),那么 body 有值,POST 无值,但是可以到 request.body 中拿到 json 数据,转成字符串类型,然后 json.loads(request.body) 即可获取到字典类型的数据

    rest framework 解析器

    **依靠请求头 content-type 对用户请求体中的数据进行解析,解析到 request.data **

    # demoapiurls
    
    urlpatterns = [
        url(r'^(?P<version>[v1|v2]+)/parser/$', views.ParserView.as_view()),
    ]
    
    # demoapiviews
    
    class ParserView(APIView):
        # 会读取请求头,JSONParser表示只能解析 content-type: application/json 头
        # FormParser表示只能解析 content-type: application/x-www-form-urlencoded 头
        parser_classes = [JSONParser, FormParser, ]
    
        def post(self, request, *args, **kwargs):
            '''
            允许用户发送JSON格式数据
                a. content-type: application/json
                b. {'name':'xi', 'age':18}
            '''
            # 获取解析后的结果,用的时候才去解析,所以是代码的起始位置
            '''
            1. 获取用户的请求
            2. 获取用户的请求体
            3. 根据用户请求头和 parser_classes = [JSONParser, FormParser, ]中支持的请求头进行比较
            4. JSONParser对象去请求体
            5. 赋值给 request.data 作为处理后的结果
            '''
            print(request.data)
            
            return HttpResponse("ParserView")
    

    源码流程

    通过 Request 找到 datadata 中有 _load_data_and_files() ,里面调用了 self._parse()self._parse() 中有 self.content_type

    图片中 344 行,select_parser() 是选择解析器,根据上面用户提交的请求头和所传的 self.parsers 来找,parsers 就是前面 views.py 中所设置的 parser_classes = [JSONParser, FormParser, ]self 是请求相关的所有数据,即请求对象,它里面有一个 contype_type ,是当前用户的 content_type 。根据这两个参数进行选择

    选择好解析器,执行解析器的 parse() 方法,如果选择的是 JSONParser 解析器,就到 JSONParserparse() 方法

    JSONParser 中执行 json.load() 方法,将 json 数据变为字典类型

    上面的内容为源码的一部分,实际上流程的入口其实还是从 dispatch 出发,对 request 进行封装

    def get_parsers(self):
        """
        Instantiates and returns the list of parsers that this view can use.
        """
        # self.parser_classes 读取的还是 APIView 中的设置
        return [parser() for parser in self.parser_classes]
    
    

    所以请求刚进来时,所有 views.py 中所设置的 parser_classes = [JSONParser, FormParser, ] 解析器全部实例化成对象,也封装到 request 中了。目前所学,Request 中有三种东西:封装的 request、认证的所有对象、解析器的所有对象,同样,解析器也可以进行全局配置

    # demodemosettings.py
    
    REST_FRAMEWORK = {
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
        "DEFAULT_VERSION": 'v1',
        "ALLOWED_VERSION": ['v1', 'v2'],
        "VERSION_PARAM": 'version',
        "DEFAULT_PARSER_CLASSES": ["rest_framework.parsers.JSONParser", "rest_framework.parsers.FormParser"]
    }
    
    # demoapiviews.py
    
    class ParserView(APIView):
    
        def post(self, request, *args, **kwargs):
            '''
            允许用户发送JSON格式数据
                a. content-type: application/json
                b. {'name':'xi', 'age':18}
            '''
            # 获取解析后的结果
            print(request.data)
            return HttpResponse("ParserView")
    

    总结

    • 使用
      • 全局配置
      • request.data
    • 源码流程
      • dispatch:request 封装
      • request.data
    • 常见的请求头
      • Referer:浏览器向 Web 服务器表明自己是从哪个网页的 URL 获得点击当前请求中的网址
      • User-Agent:浏览器表明自己的身份(是哪种浏览器)
      • Host:客户端指定自己想访问的 Web 服务器的 IP 地址和端口号
      • Accept:告诉 Web 服务器自己接受什么介质类型,*/* 表示任何类型,type/* 表示该类型下的所有子类型
    • 常见的状态码
    • 请求方法
  • 相关阅读:
    linux编程之main()函数启动过程【转】
    dlmalloc(一)【转】
    Linux进程调度原理【转】
    Linux内存管理原理【转】
    malloc原理和内存碎片【转】
    Linux MTD系统剖析【转】
    linux驱动开发:用户空间操作LCD显示简单的图片【转】
    LCD驱动分析【转】
    LCD常用接口原理【转】
    LCD之mipi DSI接口驱动调试流程【转】
  • 原文地址:https://www.cnblogs.com/qiuxirufeng/p/10473018.html
Copyright © 2020-2023  润新知