How to make a Django urlpattern accept only slugs from a model
-
03-10-2019 - |
Question
I'm making a weblog site in Django. I have a Blog model like this:
class Blog(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
...
And I want the front pages of each blog to be at URLs like this: www.example.com/blog-slug/
However, I'm also using Flatpages and will want that to be able to match URLs like this: www.example.com/flat-page/
So urlpatterns like this won't work:
urlpatterns = patterns('',
(r'^(?P<blog_slug>[-\w]+)/$', 'weblog_index', {}),
...
(r'^', include('django.contrib.flatpages.urls')),
)
because all Flatpages URLs will get trapped by the first pattern. I guess I want the first pattern to only match valid slugs from the Blog model, but I'm not sure how to do that.
Solution
You can't do this:
I guess I want the first pattern to only match valid slugs from the Blog model, but I'm not sure how to do that.
Since yes, Django only tries the first view that matches your regular expression. If that view raises a 404, it doesn't try any other URLs.
However, you can do what you're trying to do without adding anything to your urls.py
:
From the Django docs:
To install the flatpages app, follow these steps:
Install the sites framework by adding
'django.contrib.sites'
to yourINSTALLED_APPS
setting, if it’s not already in there.Also make sure you’ve correctly set
SITE_ID
to the ID of the site the settings file represents. This will usually be 1 (i.e.SITE_ID = 1
, but if you’re using the sites framework to manage multiple sites, it could be the ID of a different site.Add
'django.contrib.flatpages'
to yourINSTALLED_APPS
setting.Add
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'
to yourMIDDLEWARE_CLASSES
setting.Run the command
manage.py syncdb
.
Basically, so long as your blog apps raises an Http404
when encountering a slug for which no blog entry exists, you should be good to go.
Placing 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'
in your MIDDLEWARE_CLASSES
means that just before Django renders the error page, it checks for a FlatPage
with a path matching the URL that generated the 404 (i.e. if there's a 404, it falls back to checking for a FlatPage
). If there is one, it renders it.
OTHER TIPS
As Dominic points out, the whole point of the Flatpages app is that it automatically matches any pages that aren't caught by other views.
So, even though you can't restrict your weblog_index
view to only valid slugs, you can do a simple get_object_or_404
within that view, so that it raises a 404 error when no matching Blog slug is found - and that 404 is immediately intercepted by the Flatpages app, and all works as you want it to.