自定义 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')
  1. 我找到了一个使用 re_path 的解决方案,但我不确定这是 right/best 的方法:

     re_path('product-release/(?P<slug>[-a-zA-Z0-9_.]+)$', 
             ProductReleaseDetail.as_view(), 
             name='product-release-detail')
    
  2. 现在这不再有效(出现在上面 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(你不应该有)。

地址评论

  1. 使用 {# #} 在模板中注释掉。确保你没有使用 <!-- -->,因为它仍然会执行代码。
  2. 目前 {% url "product-release-detail" %} 是无效的:它需要一个参数,即一个 slug。如果你想 link 到列表视图,使用 {% url "product-release-list" %} 因为它可以在没有参数的情况下调用。
  3. 我不知道 {{ p }} 是什么,但我假设是产品对象。在这种情况下,您应该使用 {%url "product-release-detail" p.name_of_slug_field %}.