前提:django 的 request.POST 有值
- 请求头要求:如果请求头中的
Content-Type
为application/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
找到 data
,data
中有 _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
解析器,就到 JSONParser
的 parse()
方法
在 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/*
表示该类型下的所有子类型
- 常见的状态码
- 请求方法