Django对接PayPal触发RawPostDataException错误求助
解决Django中PayPal POST请求的RawPostDataException错误
错误信息
shippingData = json.loads(request.body) django.http.request.RawPostDataException: You cannot access body after reading from request's data stream
问题原因
Django的request.body是一次性读取的字节流,请求体数据流仅能被读取一次。如果中间件、其他代码逻辑(比如Django REST Framework的request.data)已经提前读取了请求体,再次直接访问request.body就会触发该异常。
已尝试无效操作
- 移除
request.headers相关代码 - 删除CSRF Token
- 重命名
request.body变量
有效解决方案
方案1:缓存请求体内容
在视图开头先读取并缓存请求体内容,避免重复读取触发异常:
def create_order(request): if request.method == 'POST': # 读取并解码请求体,缓存到变量中 raw_body = request.body.decode('utf-8') shippingData = json.loads(raw_body) # 后续原有逻辑保持不变 customer = Customer.objects.get(user=request.user) first_name = customer.first_name last_name = customer.last_name # 优化:直接使用创建后的对象,无需再次查询数据库 shipping_address = ShippingAddress.objects.create( customer=customer, house=shippingData['shipping']['house'], street=shippingData['shipping']['street'], city=shippingData['shipping']['city'], postcode=shippingData['shipping']['postcode'], ) # 直接使用刚创建的shipping_address对象 house = shipping_address.house street = shipping_address.street city = shipping_address.city postcode = shipping_address.postcode # 剩余代码...
方案2:使用Django REST Framework的request.data(推荐)
如果项目使用了Django REST Framework(DRF),直接用request.data即可自动解析JSON请求体,且不会触发重复读取问题:
from rest_framework.views import APIView from rest_framework.response import Response class CreateOrderView(APIView): def post(self, request): customer = Customer.objects.get(user=request.user) # 直接使用request.data获取解析后的JSON数据 shippingData = request.data first_name = customer.first_name last_name = customer.last_name shipping_address = ShippingAddress.objects.create( customer=customer, house=shippingData['shipping']['house'], street=shippingData['shipping']['street'], city=shippingData['shipping']['city'], postcode=shippingData['shipping']['postcode'], ) # 剩余代码... # 最后返回PayPal订单ID给前端,匹配前端解析逻辑 paypal_response = requests.post('https://api.sandbox.paypal.com/v2/checkout/orders', headers=headers, json=data) return Response({"orderID": paypal_response.json()["id"]})
额外代码优化
- 避免重复查询数据库:创建
ShippingAddress后直接使用返回的对象,无需再次执行filter查询 - 确保视图最后返回JSON格式的
orderID,匹配前端fetch后的解析逻辑
前端代码说明
你的前端fetch请求格式正确,已正确传递JSON格式的配送信息和CSRF Token,无需修改。
内容的提问来源于stack exchange,提问作者David Henson
相关产品推荐
相关产品推荐

