学习《Django 3 by Example》时遭遇404错误:No Order matches the given query的解决请求
我正在跟着《Django 3 by Example》学习Django,按书中步骤操作时遇到了这个404错误,具体错误信息如下:
Page not found (404) No Order matches the given query.
Request Method: GET
Request URL: http://127.0.0.1:8000/payment/process/
Raised by: payment.views.payment_process
使用FlixKart.urls中定义的URLconf,Django按以下顺序尝试了这些URL模式:
admin/
cart/
orders/
payment/ process/ [name='process']
当前路径payment/process/匹配了最后一个模式。
相关代码
支付应用(payment)的views.py
def payment_process(request): order_id = request.session.get('order_id') order = get_object_or_404(Order, id=order_id) total_cost = order.get_total_cost() if request.method == 'POST': # retrieve nonce nonce = request.POST.get('payment_method_nonce', None) # create and submit transaction result = gateway.transaction.sale({ 'amount': f'{total_cost:.2f}', 'payment_method_nonce': nonce, 'options': { 'submit_for_settlement': True } }) if result.is_success: # mark the order as paid order.paid = True # store the unique transaction id order.braintree_id = result.transaction.id order.save() return redirect('payment:done') else: return redirect('payment:canceled') else: # generate token client_token = gateway.client_token.generate() return render(request, 'payment/process.html', {'order': order,'client_token': client_token})
项目根urls.py
urlpatterns = [ path('admin/', admin.site.urls), path('cart/', include('cart.urls', namespace='cart')), path('orders/', include('orders.urls', namespace='orders')), path('payment/', include('payment.urls', namespace='payment')), path('', include('shop.urls', namespace='shop')), ]
问题分析与解决方案
这个错误的核心原因是**request.session.get('order_id')没有获取到有效的订单ID**,导致get_object_or_404(Order, id=order_id)找不到对应的订单,从而抛出404异常。下面是几个排查和解决的方向:
1. 检查订单创建视图是否正确存入order_id到session
按照《Django 3 by Example》的流程,用户完成订单表单提交后,应该在订单创建视图中将生成的order_id存入session,这样支付视图才能读取到。你需要确认orders应用的订单创建视图(通常是order_create)里有没有这段关键代码:
def order_create(request): cart = Cart(request) if request.method == 'POST': form = OrderCreateForm(request.POST) if form.is_valid(): order = form.save() # 处理订单商品逻辑(比如创建OrderItem记录) # 关键:将order_id存入session request.session['order_id'] = order.id # 清空购物车并跳转到支付页面 cart.clear() return redirect('payment:process') # ...其他表单渲染代码
如果这段代码缺失,session里就没有order_id,支付视图自然找不到订单。
2. 排查session是否正常工作
可以在支付视图中临时添加打印语句,查看order_id的取值:
def payment_process(request): order_id = request.session.get('order_id') print("当前session中的order_id:", order_id) # 查看控制台输出 order = get_object_or_404(Order, id=order_id) # ...其他代码
如果控制台输出None,说明session确实没有存储order_id,回到订单创建视图检查逻辑。另外确保Django的session配置正常(默认使用数据库session,只要执行过migrate就没问题)。
3. 防止用户直接访问支付页面
如果用户跳过订单创建流程,直接手动输入/payment/process/,session里肯定没有order_id。可以在支付视图中添加前置判断,引导用户走正确流程:
def payment_process(request): order_id = request.session.get('order_id') if not order_id: # 重定向到购物车页面,让用户先创建订单 return redirect('cart:cart_detail') order = get_object_or_404(Order, id=order_id) # ...其他代码
4. 确认数据库中存在对应订单
登录Django admin,查看orders_order表,确认有没有已创建的订单记录。如果订单根本没保存到数据库,那不管怎么找都找不到,这时候需要检查订单创建视图中form.save()是否正常执行,有没有表单验证失败的情况。
内容的提问来源于stack exchange,提问作者Kaustubh Sariputra

