1

I've encountered a one nasty bug in my code while developing a personal blog in Django. Basically, I've changed my urls.py file by adding a couple of rules to make certain views accessible.

urls.py

from django.conf.urls import include, url
from django.contrib import admin

from blog import views


urlpatterns = [
    # Examples:
    # url(r'^$', 'blogas.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^admin/', include(admin.site.urls)),
    url(r'^$', views.index, name='index'),
    url(r'^(?P<slug>\w+)', views.view_post, name='view_blog_post'),
    url(r'^about/$', views.about, name='about'),
    url(r'^posts/$', views.posts, name='posts'),

]

Everything seems to be working except when I try access http://127.0.0.1:8000/about or /posts, Django throws out a 404 error. What is the reason of this? I've defined both rules but the system seems not to recognize the pattern - maybe I've mispelled something? Maybe I know nothing about url formatting (could be, it's my first time doing this stuff)?

A big thanks from a newbie programmer to everyone who finds the bug :)

2 Answers 2

5

The url-patterns are processed from top to bottom. Your third pattern ^(?P<slug>\w+) consumes everything, so about and posts is never reached.

An example: Django wants to find the view for the url about/. The patterns ^admin/ and ^$ do not match. But ^(?P<slug>\w+) does, because about starts with letters or numbers (the character sets contained in \w)

>>> import re
>>> re.search('^(?P<slug>\w+)', 'about/')
<_sre.SRE_Match object at 0x10b5b7be8>

So Django found a match, callBs views.view_post and finishes the request. That means, the more specific rule must come first. Better: avoid ambiguity.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for advice. Still, I want to know why they are never reached (the mechanics behind this phenomenon) so I could tackle this problem easier in the future.
2

You have to change position of url(r'^(?P<slug>\w+)', views.view_post, name='view_blog_post'),.

 urlpatterns = [
        # Examples:
        # url(r'^$', 'blogas.views.home', name='home'),
        # url(r'^blog/', include('blog.urls')),

        url(r'^admin/', include(admin.site.urls)),
        url(r'^$', views.index, name='index'),
        url(r'^about/$', views.about, name='about'),
        url(r'^posts/$', views.posts, name='posts'),
        url(r'^(?P<slug>\w+)', views.view_post, name='view_blog_post'),
        ]

urlpatterns is list and order of urls is important.

3 Comments

Thank you for the solution yet it seems page is only reachable with a slash. Without one, it still shows me 404. How do I get around this?
Try this url(r'^(?P<slug>\w+)/$', views.view_post, name='view_blog_post')
I don't know why, but it works! Maybe a little explanation? :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.