Reputation: 4043
I wrote a custom field validator for slugs in my URLs (accepting periods in slugs for one model, 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},
)
The field in models.py
:
slug = models.CharField(max_length=64, null=True, blank=True,
validators=[validate_my_slug])
This works when saving models in Django admin. But then in my URLConf, this no longer works (it did work before changing the slug validation):
path('product-release/<slug:slug>', ProductReleaseDetail.as_view(),
name='product-detail')
I found a solution using re_path
, but I'm not sure it's the right/best way to do it:
re_path('product-release/(?P<slug>[-a-zA-Z0-9_.]+)$',
ProductReleaseDetail.as_view(),
name='product-release-detail')
Now this no longer works (comes before the re_path
pattern above in urls.py
):
path('product-releases', ProductReleaseList.as_view(),
name='product-release-list')
Everything works except those matches to product release list. When I changed the slug validator, the URL http://localhost:8080/product-releases
stopped working, with the error:
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_.]+$)']
But this seems wrong since I'm not even trying to reach product-release-detail
; I'm trying to reach product-release-list
. I must be missing something simple here, but now my vision is clouded.
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>
. . .
Upvotes: 0
Views: 498
Reputation:
In your template you're using something akin to:
{% url "product-release-detail" varname %}
This variable however can apparently be empty (or is even always empty due to a spelling mistake). With /<slug:slug>
this goes through (which I don't agree with btw, but that's besides the point). With your more restrictive and better re_path
, this now generates an error (correctly), because /product-release/
is not a valid url: a slug should at least have one character.
So the root cause is ether, that the variable is incorrectly named or that you have products without slugs (which you shouldn't have).
{# #}
. Make sure you didn't use <!-- -->
, because that still executes the code.{% url "product-release-detail" %}
is invalid: it requires an argument, namely a slug. If you want to link to the list view, use {% url "product-release-list" %}
as that can be called without argument.{%url "product-release-detail" p.name_of_slug_field %}
.Upvotes: 1