Django返回404错误:未找到匹配的Order Item请求助排查
为什么Django返回"Page not found (404) No order item matching the query"错误?
错误信息
"Page not found (404) No order item matching the query"
问题核心
你的OrderDetail视图继承自DetailView且指定了model = Order,但重写的get_queryset方法返回的是OrderItem的查询集合,这直接造成逻辑冲突:
DetailView的设计目标是展示单个模型对象,这里指定的是Order模型,原本会根据order_id去Order表中匹配对应订单。- 但你返回的
OrderItem查询集,会让Django尝试用传入的order_id去匹配OrderItem的主键ID,而非Order的ID,自然找不到对应数据,触发404错误。
你打印的queryset显示存在符合条件的OrderItem,但这和DetailView需要的单个Order对象没有关联。
相关代码展示
视图代码
class OrderDetail(DataMixin, DetailView): model = Order template_name = 'orders/order_detail.html' context_object_name = 'order' pk_url_kwarg = 'order_id' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) c_def = self.get_user_context() return context | c_def | {'title': 'Заказ'} def get_queryset(self): queryset = OrderItem.objects.filter(order_id=self.kwargs['order_id']) return queryset
主URL配置
urlpatterns = [ path('admin/', admin.site.urls), path('', include('home.urls', namespace='home')), path('cart/', include('cart.urls', namespace='cart')), path('orders/', include('orders.urls', namespace='orders')), path('users/', include('users.urls', namespace='users')), ]
orders应用URL配置
app_name = 'orders' urlpatterns = [ path('order/<int:order_id>/', OrderDetail.as_view(), name='order_detail'), path('create/', OrderCreateView.as_view(), name='order_create'), ]
模型定义
class Order(models.Model): username = models.CharField(max_length=100, verbose_name='Логин') first_name = models.CharField(max_length=50, verbose_name='Имя') last_name = models.CharField(max_length=50, verbose_name='Фамилия') email = models.EmailField() address = models.CharField(max_length=250, verbose_name='Адрес') postal_code = models.CharField(max_length=20, verbose_name='Почтовый индекс') city = models.CharField(max_length=100, verbose_name='Город') created = models.DateTimeField(auto_now_add=True, verbose_name='Создан') updated = models.DateTimeField(auto_now=True, verbose_name='Обновлен') paid = models.BooleanField(default=False, verbose_name='Оформлен') class Meta: ordering = ('-created',) verbose_name = 'Заказ' verbose_name_plural = 'Заказы' def __str__(self): return f'Order {self.id}' def get_total_cost(self): total_cost = self.items.aggregate(total_cost=Sum('price'))['total_cost'] return total_cost or 0 class OrderItem(models.Model): order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE) product = models.ForeignKey(Product, related_name='order_items', on_delete=models.CASCADE) price = models.DecimalField(max_digits=10, decimal_places=2) quantity = models.PositiveIntegerField(default=1) def __str__(self): return f'{self.id}' def get_cost(self): return self.price * self.quantity
模板代码
<a class="link-secondary" href="{% url 'orders:order_detail' order_id %}">Изменить</a>
解决方法
删除错误的
get_queryset重写方法:OrderDetail是用来展示单个Order对象的,无需返回OrderItem查询集,直接让DetailView默认根据order_id去Order表中查找对象即可。在模板中访问订单对应的商品项:
由于Order和OrderItem通过外键关联且设置了related_name='items',可在模板中直接通过{{ order.items.all }}获取该订单下的所有OrderItem。
修改后的视图代码:
class OrderDetail(DataMixin, DetailView): model = Order template_name = 'orders/order_detail.html' context_object_name = 'order' pk_url_kwarg = 'order_id' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) c_def = self.get_user_context() # 若需提前将OrderItem放入上下文,可添加此行 # context['order_items'] = self.object.items.all() return context | c_def | {'title': 'Заказ'}
修改后Django会正确根据order_id找到对应的Order对象,同时你可在模板中轻松获取该订单下的所有商品项,不会再触发404错误。
内容的提问来源于stack exchange,提问作者S99P
相关产品推荐
相关产品推荐

