You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:27:50