I'm trying to write a slug field so users can view my activity_detail
page. I think I wrote the code right, but I'm getting 404 error with No Activity matches the given query.
. Here is my code:
my urls.py
from django.urls import re_path
from . views import activity_list, activity_detail, activity_index
app_name = 'activity'
urlpatterns = [
re_path(r'^$', activity_index, name='index'),
re_path(r'^(?P<year>[0-9]{4})/$', activity_list, name='list'),
re_path(r'^(?P<year>[0-9]{4})/(?P<slug>[\w-]+)/$', activity_detail, name='detail'),
]
my views.py:
def activity_detail(request, year, slug=None):
activity = get_object_or_404(Activity, year=year, slug=slug)
context = {
'activity': activity,
}
return render(request, "activity/detail.html", context)
I'm planning to call my url addresses from the browser as follows:
http://localhost/activity/
http://localhost/activity/2018/
http://localhost/activity/2018/myactivity
The only problem with this approach is that if you do not specify the slug
, then the view is called with slug=None
, and thus then you filter with slug=None
, which will fail.
You can solve this with a None
check:
def activity_detail(request, year, slug=None):
filter = {'year': year}
if slug is not None:
filter['slug'] = slug
activity = get_object_or_404(Activity, **filter)
context = {
'activity': activity,
}
return render(request, "activity/detail.html", context)
So here we first make an initial filter
dictionary that contains only the year
, and if slug
is not None
, then we add an extra filter.
I find however the year
filter rather strange: typically there will be multiple Activity
s for a given year
, so then this will error.
In case you obtain an error like:
No Activity matches the given query.
This thus means that there is no record in your databases that has the given year, and slug. The 404 error is not a problem: it simply says that for that given URL, there is no corresponding Activity
object available. So it makes sense to return such error.
In case you want to display all the Activity
s that match the filter, you can use the get_list_or_404
[Django-doc].