自定义 Django SlugField 验证中断 URL 匹配
Custom Django SlugField Validation Breaks URL Matching
我在我的 URL 中为 slugs 写了一个自定义字段验证器(接受一个模型的 slugs 句点,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
的解决方案,但我不确定这是 right/best 的方法:
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>
. . .
在您的模板中,您使用的是类似于:
{% url "product-release-detail" varname %}
但是这个变量显然可以是空的(或者由于拼写错误甚至总是空的)。使用 /<slug:slug>
这会通过(我不同意顺便说一句,但这不是重点)。由于 re_path
更严格、更好,这现在会产生一个错误(正确),因为 /product-release/
不是有效的 url:一个 slug 至少应该有一个字符。
所以根本原因是以太,变量命名不正确,或者你的产品没有 slug(你不应该有)。
地址评论
- 使用
{# #}
在模板中注释掉。确保你没有使用 <!-- -->
,因为它仍然会执行代码。
- 目前
{% url "product-release-detail" %}
是无效的:它需要一个参数,即一个 slug。如果你想 link 到列表视图,使用 {% url "product-release-list" %}
因为它可以在没有参数的情况下调用。
- 我不知道 {{ p }} 是什么,但我假设是产品对象。在这种情况下,您应该使用
{%url "product-release-detail" p.name_of_slug_field %}
.
我在我的 URL 中为 slugs 写了一个自定义字段验证器(接受一个模型的 slugs 句点,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
的解决方案,但我不确定这是 right/best 的方法: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>
. . .
在您的模板中,您使用的是类似于:
{% url "product-release-detail" varname %}
但是这个变量显然可以是空的(或者由于拼写错误甚至总是空的)。使用 /<slug:slug>
这会通过(我不同意顺便说一句,但这不是重点)。由于 re_path
更严格、更好,这现在会产生一个错误(正确),因为 /product-release/
不是有效的 url:一个 slug 至少应该有一个字符。
所以根本原因是以太,变量命名不正确,或者你的产品没有 slug(你不应该有)。
地址评论
- 使用
{# #}
在模板中注释掉。确保你没有使用<!-- -->
,因为它仍然会执行代码。 - 目前
{% url "product-release-detail" %}
是无效的:它需要一个参数,即一个 slug。如果你想 link 到列表视图,使用{% url "product-release-list" %}
因为它可以在没有参数的情况下调用。 - 我不知道 {{ p }} 是什么,但我假设是产品对象。在这种情况下,您应该使用
{%url "product-release-detail" p.name_of_slug_field %}
.