如何在Django middleware中获取传入POST数据并解决RawPostDataException错误
报错原因
该错误核心是Django的
request.body对应的输入流仅支持单次读取:浏览器发送application/x-www-form-urlencoded或multipart/form-data类型的POST请求时,Django会在解析request.POST的阶段提前读取body数据流,后续再调用request.body就会触发RawPostDataException;Postman测试正常通常是因为你发送的是application/json类型请求,Django默认不会提前解析这类请求的body,首次读取可以正常执行。
可行解决方案
方案1:缓存body内容避免二次读取流
在middleware中读取body后手动赋值给Django预留的私有属性request._body,Django后续读取body时会优先检查该属性是否存在,存在就直接返回缓存内容,不会再读取输入流:
def __call__(self, request): # 先判断是否已有缓存的body,避免重复读取流 if not hasattr(request, '_body'): # 读取流内容并缓存 request._body = request.body # 后续所有需要用到body的地方都用缓存的request._body dict_str = request._body.decode("UTF-8") # 继续执行后续中间件、视图逻辑 response = self.get_response(request) return response
方案2:表单类型请求直接读取request.POST
如果业务仅需要处理表单格式的POST参数,不需要解析JSON等自定义格式,直接读取request.POST即可,不会触发数据流读取冲突:
# 直接获取解析后的表单参数字典,无需自行解码body post_data = request.POST.dict()
方案3:DRF项目直接读取request.data
如果你使用Django REST Framework开发接口,DRF已经封装了body的缓存和多格式解析逻辑,直接读取request.data就能拿到解析后的请求参数,不会触发该报错。
注意事项
- 不要在middleware中反复调用
request.body,所有读取操作统一使用提前缓存的属性 - 处理带文件上传的
multipart/form-data请求时,不要自行解码body,会破坏文件二进制内容,直接通过request.POST和request.FILES读取参数即可
内容的提问来源于stack exchange,提问作者Dhruv Singhal
相关产品推荐
相关产品推荐

