Search code examples
djangourl-pattern

How to make a Django urlpattern accept only slugs from a model


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:

    1. Install the sites framework by adding 'django.contrib.sites' to your INSTALLED_APPS setting, if it’s not already in there.

    2. 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.

    3. Add 'django.contrib.flatpages' to your INSTALLED_APPS setting.

    4. Add 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' to your MIDDLEWARE_CLASSES setting.

    5. 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.