如何多次访问WSGIRequest?解决Django请求流读取异常
解决方案:解决DRF视图调用后无法重复访问请求体的问题
问题原因
Django原生HttpRequest的请求体流是一次性可读的,当调用A.as_view()(request._request)时,视图A会读取这个流解析请求数据,流的指针会移动到末尾。之后再尝试访问request.data(DRF的Request对象会再次尝试读取原生请求流),就会触发RawPostDataException异常。
方法一:重置原生请求的可重复读取流
在调用视图A之前,先读取原生请求的body并替换为可重复读取的BytesIO流,确保流被读取后仍能重新访问:
from rest_framework import views from rest_framework.response import Response from io import BytesIO from A.views import A class B(views.APIView): def post(self, request, *args, **kwargs): # 读取并缓存原生请求的body original_body = request._request.body # 将原生request的stream替换为可重复读取的BytesIO request._request.stream = BytesIO(original_body) # 调用视图A http_response = A.as_view()(request._request) # 将流指针重置到开头,保证后续访问request.data正常读取 request._request.stream.seek(0) # 此时可正常访问request.data # 示例:validated_data = request.data return Response(http_response.data)
方法二:先缓存DRF解析数据,构造新请求给视图A
利用DRF的Request自动缓存request.data的特性,先让DRF完成数据解析,再基于缓存的body构造新的原生请求给视图A,避免原请求流被耗尽:
from rest_framework import views from rest_framework.response import Response from django.http import HttpRequest from A.views import A class B(views.APIView): def post(self, request, *args, **kwargs): # 触发DRF解析数据,自动缓存到request.data request_data = request.data # 构造新的原生HttpRequest对象,复用原请求的核心数据 new_request = HttpRequest() new_request.method = request.method new_request.body = request.body new_request.META = request._request.META.copy() # 若需处理文件上传,可按需复制request._request.FILES # 用新请求调用视图A http_response = A.as_view()(new_request) # 原request.data可正常访问,不受视图A的影响 return Response(http_response.data)
内容的提问来源于stack exchange,提问作者Wadhah Sky
相关产品推荐
相关产品推荐

