0

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.

Phil Gyford
  • 13,432
  • 14
  • 81
  • 143

2 Answers2

1

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.

Community
  • 1
  • 1
Dominic Rodger
  • 97,747
  • 36
  • 197
  • 212
  • I'm not sure I follow... I've now tried setting up a 'weblog_index' view which does a get_object_or_404() using the matched blog_slug. This works in that the correct page is shown, but if it fails, it doesn't move on to trying to match the Flatpages URL. – Phil Gyford Sep 16 '10 at 11:40
  • (Which I wouldn't really expect it to - once Django has matched a URL and moved on to the View, it's not going to go back and try more URLs after is it...?) – Phil Gyford Sep 16 '10 at 11:41
  • I think the OP is asking to match the flat page views with the slug field values. – Ankit Jaiswal Sep 16 '10 at 11:43
  • @anand - sorry, I don't understand what you're saying. I'm 99% certain I understand @Phil's question though... – Dominic Rodger Sep 16 '10 at 11:45
  • What I can understand from the question is that Phil wants to create some url patterns based on the slug fields in his model and then make the flat page urls to work with those urls. Please correct me if I am wrong. – Ankit Jaiswal Sep 16 '10 at 11:51
  • That's not right @anand. If the URL matches a blog_slug I want the front page of that Blog to display. If the URL doesn't match a blog_slug I want Flatpages to deal with the request (and either display a matching Flatpage, or 404, as appropriate). – Phil Gyford Sep 16 '10 at 12:02
  • hmm, I did not get it first time. I apologize for that. – Ankit Jaiswal Sep 16 '10 at 12:04
  • And yes, I should thank you too Dominic - I assumed I'd set flatpages up correctly when I hadn't added the middleware. So cheers. – Phil Gyford Sep 16 '10 at 12:53
1

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.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I must be doing something wrong then, because if I use the URL of a known Flatpage, then the weblog_index view generates a 404, because the URL doesn't contain a valid blog_slug, and the browser displays a 404 ("No Blog matches the given query."). It *doesn't* get intercepted by the Flatpages app. – Phil Gyford Sep 16 '10 at 12:01
  • And, yes, I *was* doing something wrong! I'd neglected to add 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' to my MIDDLEWARE_CLASSES setting. So it wasn't looking for Flatpages after 404s, and was only relying on all the URL matching to fail. Thanks for your answer Daniel, which prompted me to question what I was doing and re-read the docs! – Phil Gyford Sep 16 '10 at 12:25