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

使用For循环与url方法时Django抛出NoReverseMatch错误的原因

问题:Django模板For循环中使用entry迭代器和url模板方法时触发NoReverseMatch错误

错误信息

NoReverseMatch at /
Reverse for 'entry' with keyword arguments '{'title': ''}' not found. 1 pattern(s) tried:['wiki/(?P[^/]+)\Z'] Line 12.

模板代码

{% extends "encyclopedia/layout.html" %}

{% block title %}
    Encyclopedia
{% endblock %}

{% block body %}
    <h1>All Pages</h1>

    <ul>
        {% for entry in entries %}
            <li><a href="{% url 'entry'  title=entry %}">{{ entry }}</a></li> 
            {% comment %} <p> {{ entry }} </p> {% endcomment %}
        {% endfor %}
    </ul> 
        {% comment %} <a href "/wiki/{{ entry }}"> <li>{{ entry }}</li> </a> {% endcomment %}

{% endblock %}

补充说明

尝试在页面中打印带链接的条目列表,模板可正常输出列表元素,但使用url模板方法时页面无法渲染,触发上述错误。

urls.py代码

from django.urls import path

from . import views

urlpatterns = [
    path("", views.index, name="index"),
    path("wiki/<str:title>", views.entry, name="entry"),
    path("search/", views.search, name="search"),
    path("new/", views.new_page, name="new_page"),
    path( "edit/", views.edit, name="edit"),
    path( "save_edit/", views.save_edit, name="save_edit"),
    path( "rand/", views.rand, name= "rand")
]

views.py代码

from django.shortcuts import render
import markdown
from . import util
import random

def convert_md_to_html(title):
    content = util.get_entry(title)
    markdowner = markdown.Markdown()
    if content == None:
        return None
    else:
        return markdowner.convert(content)


def index(request):
    return render(request, "encyclopedia/index.html", {
        "entries": util.list_entries()
        
    })

def entry(request, title):
    html_content = convert_md_to_html(title)
    if html_content == None:
        return render(request, "encyclopedia/error.html",{
            "message": "This entry does not exist"
        })
    else:
        return render(request, "encyclopedia/entry.html",{
            "title": title,
            "content": html_content
        })
    
def search(request):
    if request.method == "POST":
        entry_search = request.POST['q']
        html_content = convert_md_to_html(entry_search)
        if html_content is not None:
            return render(request, "encyclopedia/entry.html",{
                "title": entry_search,
                "content":html_content
        })

        else:
            allEntries = util.list_entries()
            recommendation = []
            for entry in allEntries:
                if entry_search.lower() in entry.lower():
                    recommendation.append(entry)
            return render(request, "encyclopedia/search.html", {
                "recommendation": recommendation
            })
        
def new_page(request):
    if request.method == "GET":
        return render(request, "encyclopedia/new.html")
    else:
        title = request.POST['title']
        content = request.POST['content']
        titleExist = util.get_entry(title)
        if titleExist is not None:
            return render(request, "encyclopedia/error.html", {
                "message": "Entry page already exist"
            })
        else:
            util.save_entry(title, content)
            html_content = convert_md_to_html(title)
            return render(request, "encyclopedia/entry.html", {
                "title": title,
                "content": html_content
            })

def edit(request):
    if request.method == 'POST':
        title = request.POST['entry_title']
        content = util.get_entry(title)
        return render(request, "encyclopedia/edit.html",{
            "title": title,
            "content": content
        })

def save_edit(request):
    if request.method == "POST":
        title = request.POST['title']
        content = request.POST['content']
        util.save_entry(title, content)
        html_content = convert_md_to_html(title)
        return render(request, "encyclopedia/entry.html",{
            "title": title,
            "content": html_content
        })

def rand(request):
    allEntries = util.list_entries()
    rand_entry = random.choice(allEntries)
    html_content = convert_md_to_html(rand_entry)
    return render(request, "encyclopedia/entry.html",{
        "title" : rand_entry,
        "content" : html_content
    })

问题分析与解决方法

错误提示明确显示title参数为空字符串,说明util.list_entries()返回的列表中存在空元素,导致循环时entry为空,无法匹配wiki/<str:title>的路由规则(该规则要求title为非空字符串)。

解决步骤:

  1. 修复条目列表生成逻辑:检查util.py中的list_entries函数,确保返回的列表过滤掉空字符串。例如:

    def list_entries():
        # 原有读取文件逻辑
        entries = [f[:-3] for f in os.listdir("entries") if f.endswith(".md")]
        # 过滤空条目
        return [entry for entry in entries if entry.strip()]
    
  2. 模板中添加空值过滤:在循环时跳过空的entry,避免生成无效URL:

    {% for entry in entries %}
        {% if entry %}
            <li><a href="{% url 'entry' title=entry %}">{{ entry }}</a></li>
        {% endif %}
    {% endfor %}
    
  3. 路由规则优化(可选):如果业务允许处理空标题(不推荐),可修改路由为path("wiki/<str:title>/", views.entry, name="entry")并在视图中处理空标题场景,但更合理的做法是确保传入的title始终有效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 13:08:11