Reputation: 1806
I have 2 URL's with a slug field in the URL.
url(r'^genres/(?P<slug>.+)/$', views.genre_view, name='genre_view'),
url(r'^genres/(?P<slug>.+)/monthly/$', views.genre_month, name='genre_month'),
The first one opens fine but the second one gives a DoesNotExist
error saying Genres matching query does not exist
.
Here is how I'm accessing the 2nd URL in my HTML
<li><a href="{% url 'genre_month' slug=genre.slug %}">Monthly Top Songs</a></li>
I tried to print the slug in the view. It is passed as genre_name/monthly
instead instead of genre_name
.
I think the problem is with the regex in the URLs. Any idea what's wrong here?
Upvotes: 17
Views: 18344
Reputation: 25022
Django always uses the first pattern that matches. For urls similar to genres/genre_name/monthly
your first pattern matches, so the second one is never used. The truth is the regex is not specific enough, allowing all characters - which doesn't seem to make sense.
You could reverse the order of those patterns, but what you should do is to make them more specific (compare: urls.py example in generic class-based views docs):
url(r'^genres/(?P<slug>[-\w]+)/$', views.genre_view, name='genre_view'),
url(r'^genres/(?P<slug>[-\w]+)/monthly/$', views.genre_month, name='genre_month'),
Edit 2020:
Those days (since Django 2.0), you can (and should) use path
instead of url
. It provides built-in path converters, including slug
:
path('genres/<slug:slug>/', views.genre_view, name='genre_view'),
path('genres/<slug:slug>/monthly/', views.genre_month, name='genre_month'),
Upvotes: 30
Reputation: 27436
In Django >= 2.0, slug is included in URL by doing it like below.
from django.urls import path
urlpatterns = [
...
path('articles/<slug:some_title>/', myapp.views.blog_detail, name='blog_detail'),
...
]
Source: https://docs.djangoproject.com/en/2.0/ref/urls/#django.urls.path
Upvotes: 5
Reputation: 469
I believe that you can also drop the _
from the pattern that @Ludwik has suggested and revise to this version (which is one character simpler :) ):
url(r'^genres/(?P<slug>[-\w]+)/$', views.genre_view, name='genre_view'),
url(r'^genres/(?P<slug>[-\w]+)/monthly/$', views.genre_month, name='genre_month'),
Note that \w
stands for "word character". It always matches the ASCII characters [A-Za-z0-9_]
. Notice the inclusion of the underscore and digits. more info
Upvotes: 11