Search code examples
pythondjangodjango-urlsslug

Django url No Activity matches the given query?


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

Solution

  • 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 Activitys 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 Activitys that match the filter, you can use the get_list_or_404 [Django-doc].