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

Django点击Category出现NoReverseMatch错误的原因排查

Django分类导航报错:Reverse for 'category_2' with arguments '('',)' not found

需求场景

要实现的功能流程:

  • 点击页面顶部导航栏的「Category」,展示所有可用分类
  • 点击单个分类,显示该分类下的所有商品
  • 点击商品名称,进入对应商品的详情页

但第一步点击「Category」时触发错误,错误信息如下:

Request Method: GET
Request URL: http://127.0.0.1:8000/category
Exception Type: NoReverseMatch at /category
Exception Value: Reverse for 'category_2' with arguments '('',)' not found. 1 pattern(s) tried: ['category_2/(?P<cat_id>[0-9]+)/\\Z']

相关代码

views.py

def product_detail(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    comments = Comment.objects.filter(product=product)
    offers = PriceOffer.objects.filter(product=product).order_by('-offer_price')
    off_list = [float(product.first_bid)]
    maximum = float(product.first_bid)

    if request.method == 'POST':
        # comment逻辑
        # offer逻辑

    context = {
        'product': product,
        'comments': comments, 
        'offers': offers,
        'off' : off
    }

    return render(request, 'auctions/product_detail.html', context)

def category(request):
    categories = Category.objects.all()
    return render(request, 'auctions/category.html', {'categories': categories})

def category_2(request,cat_id):
    category = Category.objects.get(id=cat_id)
    products = Product.objects.filter(category=category)
    return render(request, 'auctions/product_detail.html', {'category': category, 
    'products': products})

urls.py

path("product_detail/<int:product_id>/", views.product_detail, name="product_detail"),
path("category", views.category, name="category"),
path("category_2/<int:cat_id>/", views.category_2, name="category_2"),

category.html

{% extends "auctions/layout.html" %}
{% block body %}
    <h2>All Categories</h2>
    {% for category in categories %}
        <h3><a href="{% url 'category_2' category.pk %}">{{ category.name }}</a></h3>
    {% endfor %}
{% endblock %}

product_detail.html(相关部分)

<h2>{{ category.name }}</h2>
{% for product in products %}
    <h3>{{ product.name }}</h3>
{% endfor %}

layout.html(顶部导航部分)

{% load static %}

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>{% block title %}Auctions{% endblock %}</title>
    </head>
    <body>
        <h1>Auctions</h1>
         <div>
            {% if user.is_authenticated %}
                Signed in as <strong>{{ user.username }}</strong>.
            {% else %}
                Not signed in.
            {% endif %}
       </div>
       <ul class="nav">
            <li class="nav-item">
                <a class="nav-link" href="{% url 'index' %}">Active Listings</a>
            </li>

            <li class="nav-item">
                <a class="nav-link" href="{% url 'category' %}">Category</a>
            </li>

        {% if user.is_authenticated %}
            <li class="nav-item">
                    <a class="nav-link" href="{% url 'logout' %}">Log Out</a>
            </li>
        {% else %}
            <li class="nav-item">
                <a class="nav-link" href="{% url 'login' %}">Log In</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="{% url 'register' %}">Register</a>
            </li>
        {% endif %}
    </ul>
    <hr>
    {% block body %}
    {% endblock %}
</body>

错误原因

报错核心是循环中的某个category对象的pk为空字符串,模板执行{% url 'category_2' category.pk %}时,无法生成符合要求的URL——因为category_2路由要求传入整数类型的cat_id,空字符串不匹配路由规则。

可能的触发点:

  1. 数据库中存在id(主键)为空的Category无效记录
  2. 分类查询时意外获取到了未初始化的空对象

解决方案

1. 清理无效分类数据

检查数据库中的Category表,删除或修复id为空的无效记录,确保所有分类都有合法的主键值。

2. 模板增加空值过滤

在category.html的循环中,先判断category.pk是否存在,再渲染链接,避免生成无效URL:

{% extends "auctions/layout.html" %}
{% block body %}
    <h2>所有分类</h2>
    {% for category in categories %}
        {% if category.pk %}
            <h3><a href="{% url 'category_2' category.pk %}">{{ category.name }}</a></h3>
        {% endif %}
    {% endfor %}
{% endblock %}

3. 视图层提前过滤无效数据

在category视图中,提前排除无主键的分类,避免无效数据传入模板:

def category(request):
    # 只保留有有效主键的分类
    categories = Category.objects.exclude(id__isnull=True)
    return render(request, 'auctions/category.html', {'categories': categories})

4. 修复category_2视图的异常处理

当前category_2视图用Category.objects.get(id=cat_id),如果传入的cat_id不存在会抛出DoesNotExist错误,建议改用get_object_or_404返回404页面,避免服务器崩溃:

from django.shortcuts import get_object_or_404

def category_2(request, cat_id):
    category = get_object_or_404(Category, id=cat_id)
    products = Product.objects.filter(category=category)
    # 建议创建单独的分类商品列表模板,避免和商品详情页模板混淆
    return render(request, 'auctions/category_products.html', {'category': category, 'products': products})

额外优化建议

  • 模板分离:分类商品列表和商品详情页应使用不同模板,避免变量冲突(当前用product_detail.html同时处理两种场景,容易引发逻辑混乱)
  • 路由命名优化:将category_2改为更语义化的名称,比如category_products,提升代码可读性
  • 商品跳转链接:在分类商品列表中,给商品名称添加跳转详情页的链接,完成完整流程:
    {% for product in products %}
        <h3><a href="{% url 'product_detail' product.pk %}">{{ product.name }}</a></h3>
    {% endfor %}
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 09:06:02