自定义 Django SlugField 验证会破坏 URL 匹配
Posted
技术标签:
【中文标题】自定义 Django SlugField 验证会破坏 URL 匹配【英文标题】:Custom Django SlugField Validation Breaks URL Matching 【发布时间】:2021-03-03 23:36:18 【问题描述】:我为我的 URL 中的 slug 编写了一个自定义字段验证器(一个模型接受 slug 中的句点,SLUG_REGEX = '[-a-zA-Z0-9_.]+$'
):
def validate_my_slug(value):
my_slug_re = re.compile(settings.SLUG_REGEX)
if not my_slug_re.match(value):
raise ValidationError(
_('Slugs must consist of letters, numbers, '
'underscores, hyphens, or periods.'),
params='value': value,
)
models.py
中的字段:
slug = models.CharField(max_length=64, null=True, blank=True,
validators=[validate_my_slug])
这在 Django 管理中保存模型时有效。但是在我的 URLConf 中,这不再有效(它在更改 slug 验证之前确实有效):
path('product-release/<slug:slug>', ProductReleaseDetail.as_view(),
name='product-detail')
我找到了使用 re_path
的解决方案,但我不确定这是正确/最佳的方法:
re_path('product-release/(?P<slug>[-a-zA-Z0-9_.]+)$',
ProductReleaseDetail.as_view(),
name='product-release-detail')
现在这不再有效(出现在上面 urls.py
中的 re_path
模式之前):
path('product-releases', ProductReleaseList.as_view(),
name='product-release-list')
除了与产品发布列表匹配的以外,一切正常。当我更改 slug 验证器时,URL http://localhost:8080/product-releases
停止工作,出现错误:
NoReverseMatch at /product-releases
Reverse for 'product-release-detail' with no arguments not found.
1 pattern(s) tried: ['product-release/(?P<slug>[-a-zA-Z0-9_.]+$)']
但这似乎是错误的,因为我什至没有尝试联系product-release-detail
;我正在尝试联系product-release-list
。我一定是在这里遗漏了一些简单的东西,但现在我的视野蒙上了一层阴影。
views.py
. . .
class ProductReleaseList(ListView):
model = ProductRelease
class ProductReleaseDetail(DetailView):
model = ProductRelease
. . .
urlpatterns
. . .
# Product Releases
path('product-releases', ProductReleaseList.as_view(), name='product-release-list'),
re_path('product-release/(?P<slug>[-a-zA-Z0-9_.]+$)', ProductReleaseDetail.as_view(), name='product-release-detail'),
# Release Notes
path('release-notes', ReleaseNoteList.as_view(), name='release-note-list'),
re_path('release-note/(?P<slug>[-a-zA-Z0-9_.]+$)', ReleaseNoteDetail.as_view(), name='release-note-detail'),
. . .
productrelease_list.html
. . .
<h4><a href="% url 'product-release-detail' %"> p </a></h4>
. . .
【问题讨论】:
1) 看起来不错,但 2) 没有意义。请通过复制发布完整的 urlpatterns。您可能在某处忘记了逗号或括号。 好的,但在 IDE 中没有警告或错误,并且站点的其余部分和代码正常工作。我会尽快更新。 现在说得通了。 url 与列表视图正确匹配,但在您使用的模板中 % url % 现在失败了。 我已经用更多细节更新了这个问题。我仍然不确定为什么product-releases
没有得到匹配,或者更确切地说,为什么在这里使用 slug 正则表达式。这只是列表的常规通用视图。
【参考方案1】:
在您的模板中,您使用的内容类似于:
% url "product-release-detail" varname %
然而,这个变量显然可以为空(或者由于拼写错误甚至总是为空)。使用/<slug:slug>
,这将通过(我不同意顺便说一句,但这不是重点)。使用更严格和更好的re_path
,现在(正确)会产生错误,因为/product-release/
不是有效的网址:slug 至少应该有一个字符。
所以根本原因是以太,变量命名不正确,或者你的产品没有 slug(你不应该有)。
地址 cmets
-
使用
# #
在模板中注释掉。确保您没有使用 <!-- -->
,因为它仍然会执行代码。
目前% url "product-release-detail" %
是无效的:它需要一个参数,即一个slug。如果您想链接到列表视图,请使用% url "product-release-list" %
,因为它可以不带参数地调用。
我不知道 p 是什么,但我假设是产品对象。在这种情况下,您应该使用%url "product-release-detail" p.name_of_slug_field %
。
【讨论】:
我很抱歉。我正在处理一些我不愿意分享的代码,所以我试图删除不需要的部分,以使其更清楚地解决这个问题。我想我实际上掩盖了这个问题......你是对的,但我已经测试过了(例如,在我的模板中注释掉了% url product-release-detail %
。如果你不介意,你能看看我的编辑吗?我已经说得更清楚了(我希望如此)。并且我确保所有产品版本和所有发行说明在数据库中都有 slug。
谢谢!这按预期工作。使用url
模板标签的一个基本部分完全让我无法理解。我陷入了其他细节的泥潭(比如“列表”没有出现)。您甚至在您的第一个回复中提到它需要一个论点,而我忽略了它。抱歉...再次感谢,您对我们的帮助最大。以上是关于自定义 Django SlugField 验证会破坏 URL 匹配的主要内容,如果未能解决你的问题,请参考以下文章