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

Django中payments.html带上下文重定向异常及实现方法

在Django中重定向时携带上下文参数到payments页面

Django的redirect()方法发起的是GET请求,无法直接传递上下文字典,我们可以通过会话存储或URL参数传递订单号两种方式实现需求,以下是具体方案:


方案一:利用会话(Session)存储临时数据

1. 修改place_order视图

在订单保存后,将需要的上下文数据存入session,再重定向到payments视图:

from django.shortcuts import render, redirect, HttpResponse
from carts.models import CartItem
from .forms import OrderForm
import datetime
from .models import Order

def payments(request):
    current_user = request.user
    # 从session中提取数据
    order_id = request.session.get('order_id')
    total = request.session.get('total')
    tax = request.session.get('tax')
    delivery_charge = request.session.get('delivery_charge')
    grand_total = request.session.get('grand_total')
    
    # 校验数据有效性
    if not order_id:
        return redirect('checkout')
    
    # 查询订单和购物车数据
    order = Order.objects.get(id=order_id, user=current_user, is_ordered=False)
    cart_items = CartItem.objects.filter(user=current_user)
    
    context = {
        'order': order, 
        'cart_items': cart_items, 
        'total': total, 
        'tax': tax, 
        'delivery_charge': delivery_charge, 
        'grand_total': grand_total, 
    }
    
    # 取出数据后删除session,避免重复使用
    del request.session['order_id']
    del request.session['total']
    del request.session['tax']
    del request.session['delivery_charge']
    del request.session['grand_total']
    
    return render(request, 'orders/payments.html', context)

def place_order(request, total=0, quantity=0,):
    current_user = request.user

    cart_items = CartItem.objects.filter(user=current_user)
    cart_count = cart_items.count()

    delivery_charge = 40
    grand_total = 0
    tax = 0
    for cart_item in cart_items:
        total += (cart_item.product.price * cart_item.quantity)
        quantity += cart_item.quantity
    tax = (2 * total)/100    
    grand_total = total + tax + delivery_charge

    if request.method == 'POST':
        form = OrderForm(request.POST) 
        if form.is_valid():
            data = Order()
            data.user = current_user
            data.first_name = form.cleaned_data['first_name']
            data.last_name = form.cleaned_data['last_name']
            data.phone = form.cleaned_data['phone']
            data.email = form.cleaned_data['email']
            data.address_line_1 = form.cleaned_data['address_line_1']
            data.address_line_2 = form.cleaned_data['address_line_2']
            data.country = form.cleaned_data['country']
            data.state = form.cleaned_data['state']
            data.city = form.cleaned_data['city']
            data.pincode = form.cleaned_data['pincode']
            data.order_note = form.cleaned_data['order_note']
            data.order_total = grand_total
            data.tax = tax
            data.delivery_charge = delivery_charge
            data.ip = request.META.get('REMOTE_ADDR')

            yr = int(datetime.date.today().strftime('%Y'))
            dt = int(datetime.date.today().strftime('%d'))
            mt = int(datetime.date.today().strftime('%m'))
            d = datetime.date(yr,mt,dt)
            current_date = d.strftime("%Y%m%d")
            data.save()
            # 保存后生成订单号(此时data.id已存在)
            order_number = current_date + str(data.id)
            data.order_number = order_number
            data.save()
            
            order = Order.objects.get(user=current_user, is_ordered=False, order_number=order_number)
            
            # 将上下文数据存入session
            request.session['order_id'] = order.id
            request.session['total'] = total
            request.session['tax'] = tax
            request.session['delivery_charge'] = delivery_charge
            request.session['grand_total'] = grand_total
            
            # 重定向到payments视图
            return redirect('payments')
    else:
        return redirect('checkout')

方案二:通过URL参数传递订单号(更稳定)

1. 修改URL配置

在urls.py中给payments视图添加订单号参数:

from django.urls import path
from . import views

urlpatterns = [
    # 其他URL配置...
    path('payments/<str:order_number>/', views.payments, name='payments'),
]

2. 修改place_order视图

重定向时携带订单号参数:

def place_order(request, total=0, quantity=0,):
    # 前面代码不变...
    if form.is_valid():
        # 保存订单代码不变...
        order = Order.objects.get(user=current_user, is_ordered=False, order_number=order_number)
        
        # 重定向到带订单号的payments页面
        return redirect('payments', order_number=order_number)
    else:
        return redirect('checkout')

3. 修改payments视图

通过订单号查询所有所需数据:

def payments(request, order_number):
    current_user = request.user
    # 通过订单号查询订单
    order = Order.objects.get(user=current_user, is_ordered=False, order_number=order_number)
    cart_items = CartItem.objects.filter(user=current_user)
    
    # 从订单对象中提取金额数据(或重新计算)
    total = order.order_total - order.tax - order.delivery_charge
    tax = order.tax
    delivery_charge = order.delivery_charge
    grand_total = order.order_total
    
    context = {
        'order': order, 
        'cart_items': cart_items, 
        'total': total, 
        'tax': tax, 
        'delivery_charge': delivery_charge, 
        'grand_total': grand_total, 
    }
    return render(request, 'orders/payments.html', context)

方案对比

  • 会话存储:适合传递较多临时数据,数据不会暴露在URL中,但依赖用户会话,清除会话会导致数据丢失。
  • URL参数传递订单号:更简洁稳定,即使会话丢失也能通过订单号查询数据,缺点是订单号会显示在URL中。

内容的提问来源于stack exchange,提问作者samrat ghosh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:19:57