Django reverse()跳转异常:访问无效页面陷入无限循环
Django重定向至notfound页面触发无限循环的根本原因解析
问题场景
我在开发CS50W项目1的类维基百科Django应用(应用名encyclopedia)时遇到异常:当用户访问/wiki/[无效页面名称]时,entry视图找不到对应markdown文件,代码里通过return HttpResponseRedirect(reverse("notfound"))尝试重定向到notfound页面,但实际陷入无限循环,反复进入entry视图,无法跳转到目标页面。
根本原因
核心问题出在Django的URL路由匹配规则和顺序上,和reverse()函数的使用无关——reverse("notfound")是正确通过名称生成了/wiki/notfound这个URL的,问题出在请求到达时的路由匹配阶段:
当前urls.py中,path("wiki/<str:title>", views.entry, name="entry")这个路由定义在wiki/notfound之前,而<str:title>的匹配规则是接受任何非空字符串,包括"notfound"。当重定向后的请求/wiki/notfound到达时,Django会从上到下遍历urlpatterns,第一个匹配到的是entry路由(把title参数设为"notfound"),而非notfound路由。进入entry视图后,因为不存在名为"notfound"的markdown文件,代码又会触发重定向到/wiki/notfound,由此形成无限循环。
解决方案的原理验证
你找到的两种解决方案本质都是打破路由匹配的冲突:
- 调整URL模式顺序:把
wiki/notfound路由放在wiki/<str:title>之前,这样Django会优先匹配到notfound路由,不会进入entry视图。 - 给URL模式添加斜杠:比如将
wiki/notfound改为wiki/notfound/,或wiki/<str:title>改为wiki/<str:title>/,此时/wiki/notfound和/wiki/notfound/是两个不同的URL,不会被对方的路由规则匹配,从而避免冲突。
修正后的URL配置示例
方案1:调整路由顺序
from django.urls import path from . import views urlpatterns = [ path("", views.index, name="index"), # 将notfound路由放在entry路由之前 path("wiki/notfound", views.notfound, name="notfound"), path("wiki/<str:title>", views.entry, name="entry"), ]
方案2:添加斜杠区分URL
from django.urls import path from . import views urlpatterns = [ path("", views.index, name="index"), # 给entry路由添加末尾斜杠 path("wiki/<str:title>/", views.entry, name="entry"), # 给notfound路由添加末尾斜杠 path("wiki/notfound/", views.notfound, name="notfound"), ]
内容的提问来源于stack exchange,提问作者Joseph Chemaly
相关产品推荐
相关产品推荐

