django中如何解析content-type=application/json的请求

本文由「大千AI助手」原创发布,专注用真话讲AI,回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我,一起撕掉过度包装,学习真实的AI技术!
往期文章回顾:
- 12.实测DeepSeek分词机制:你的输入如何变成计费Token? @2025-06-08 19:30:43+08:00
- 11.英语分词进化论:BPE相关论文汇总 @2025-06-08 18:43:38+08:00
- 10.硬核实战 | 3分钟Docker部署ClickHouse列存数据库 @2025-06-07 20:14:33+08:00
- 9.技术深解 | DeepSeek-R1-0528训练参数全透视:163K上下文与MoE高效架构的基石 @2025-06-07 19:23:40+08:00
- 8.DeepSeek最新升级实测:推理能力翻倍,但离世界顶尖还有多远? @2025-06-06 23:35:19+08:00
- 7.血泪教训!Redis默认配置竟会导致数据丢失?Docker生产部署指南 @2025-06-06 00:00:00+08:00
- 6.Function Call:大模型如何突破自身局限"使用工具" @2025-06-05 23:57:45+08:00
- 5.DeepSeek动手实践:创建一个自动连点器 @2025-06-04 23:59:15+08:00
- 4.告别无效提示!使用少样本学习让AI秒懂你的需求 @2025-06-03 23:46:56+08:00
- 3.解密PromptTemplate:为什么说它是AI时代的Jinja模板? @2025-06-02 21:47:23+08:00
- 2.LangChain Core架构解析:模块化设计与LCEL原语实现原理 @2025-06-01 21:02:36+08:00
- 1.拒绝重复造轮子!LangChain如何简化LLM应用开发? @2025-06-01 07:42:09+08:00
问题描述
主要问题
Django原生开发时,View视图里POST请求处理方法post
里通过request.POST
获取content-type=application/json
类型的请求的请求体的结果为空字典{}
其他观察
-
对于
content-type=application/x-www-form-urlencoded
类型的请求体能正常解析 -
对于
content-type=application/json
类型的请求,调试发现request.body
里包含请求的json字符串 -
处理视图View的入参request的类型是
django.core.handlers.wsgi.WSGIRequest
原因分析
综合分析上述问题和观察结果,猜测django在解析请求的时候根据content-type
做了特殊区分处理
分析django源码,发现request.POST
实际上是个property(POST = property(_get_post, _set_post)
)。
具体逻辑如下:
python
def _get_post(self):
if not hasattr(self, '_post'):
self._load_post_and_files()
return self._post
def _set_post(self, post):
self._post = post
而上述问题是查询的时候无法获取,因此继续跟踪_get_post
方法,_load_post_and_files
就是加载和解析post请求参数的主要逻辑,继承自django.http.request.HttpRequest
。
具体逻辑如下
python
def _load_post_and_files(self):
"""Populate self._post and self._files if the content-type is a form type"""
if self.method != 'POST':
self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()
return
if self._read_started and not hasattr(self, '_body'):
self._mark_post_parse_error()
return
if self.content_type == 'multipart/form-data':
if hasattr(self, '_body'):
# Use already read data
data = BytesIO(self._body)
else:
data = self
try:
self._post, self._files = self.parse_file_upload(self.META, data)
except MultiPartParserError:
# An error occurred while parsing POST data. Since when
# formatting the error the request handler might access
# self.POST, set self._post and self._file to prevent
# attempts to parse POST data again.
# Mark that an error occurred. This allows self.__repr__ to
# be explicit about it instead of simply representing an
# empty POST
self._mark_post_parse_error()
raise
elif self.content_type == 'application/x-www-form-urlencoded':
self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()
else:
self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()
通过分析不难发现仅仅解析如下content-type
的请求体
multipart/form-data
- 也就是文件上传application/x-www-form-urlencoded
- 其他类型 - 返回空字典(这也就解释了为啥
content-type=application/json
时获取的是个空字典)
解决方案
当抽丝剥茧找到问题的根本原因时,解决方案也就来了,那就是 自己解析 😂,当然你也可以投入djangorestframework
的怀抱,这是后话。
在构造form表单参数验证前,根据request.content_type == 'application/json'
条件判断,满足的进行json字符串解析即可
方案示例
python
def post(self, request, *args, **kwargs):
if request.content_type == 'application/json':
# 这里可以增加一些异常处理逻辑
body = json.loads(request.body)
else:
body = request.POST
# 创建form表单
form = CustomForm(body)
.... # 后续处理
One More Thing
授人以鱼不如授人以渔,本文以Django中POST
请求处理时无法通过request.POST
直接获取content-type=application/json
的请求体的问题为例,系统地展示在Django开发中遇到问题时,该如何从现象排查、问题定位、原因分析到最终解决的完整方法论。
本文由「大千AI助手」原创发布,专注用真话讲AI,回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我,一起撕掉过度包装,学习真实的AI技术!