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
相关产品推荐
相关产品推荐

