Django中如何避免create路由被<str:handle>动态参数路由匹配?
问题原因
Django 路由会按照urlpatterns列表的从上到下顺序匹配,你遇到的问题核心是路由尾部斜杠不匹配:Django 默认开启APPEND_SLASH配置,当用户访问不带尾部斜杠的URL且未匹配到路由时,会自动重定向到带斜杠的地址。你当前写的path('create', ...)仅匹配/blogs/create(无斜杠),而浏览器访问时通常会自动补全尾部斜杠变成/blogs/create/,该地址无法匹配到create路由,就会落到下方的<str:handle>路由,把create/当作handle参数传入,自然返回博客不存在的404错误。
解决方案
方案1:统一添加尾部斜杠(最推荐,符合Django默认规范)
修改blogs应用下的urls.py,给所有路由补全尾部斜杠,保证匹配顺序正常生效:
from django.urls import path from . import views app_name = 'blogs' urlpatterns = [ path('', views.index, name = 'index'), # 新增尾部斜杠 path('create/', views.create, name = 'create'), # 详情页也同步新增尾部斜杠 path('<str:handle>/', views.show, name = 'blogs'), ]
修改后访问/blogs/create/会优先命中创建页路由,不会走到详情页规则。
方案2:自定义路径转换器排除保留字
如果后续还有edit、delete这类和详情页格式一致的保留路径,可以自定义路径转换器,主动排除保留字被识别为handle参数:
- 在
blogs应用目录下新建converters.py,写入如下内容:
class HandleConverter: regex = '[^/]+' # 所有需要排除的保留字都加入该列表 reserved_words = {'create', 'edit', 'delete'} def to_python(self, value): if value in self.reserved_words: raise ValueError return value def to_url(self, value): return value
- 在
blogs应用的urls.py中注册转换器,替换原有路由规则:
from django.urls import path, register_converter from . import views from .converters import HandleConverter app_name = 'blogs' # 注册自定义转换器 register_converter(HandleConverter, 'handle') urlpatterns = [ path('', views.index, name = 'index'), path('create/', views.create, name = 'create'), # 使用自定义转换器替代默认str转换器 path('<handle:handle>/', views.show, name = 'blogs'), ]
该方案即使后续不小心调整了路由顺序,也不会出现保留字被识别为handle的问题。
方案3:调整详情页路由结构
也可以给详情页路由加固定前缀,从结构上完全避免冲突:
path('detail/<str:handle>/', views.show, name = 'blogs'),
修改后详情页URL变为/blogs/detail/xxx,和/blogs/create/这类功能路径完全区隔,不会产生匹配冲突。
内容的提问来源于stack exchange,提问作者coder-stix
相关产品推荐
相关产品推荐

