解析器

前提: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/* 表示该类型下的所有子类型
  • 常见的状态码
  • 请求方法
原文地址:https://www.cnblogs.com/qiuxirufeng/p/10473018.html