views:

63

answers:

2

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.

+1  A: 

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.

Dominic Rodger
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
(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
I think the OP is asking to match the flat page views with the slug field values.
anand
@anand - sorry, I don't understand what you're saying. I'm 99% certain I understand @Phil's question though...
Dominic Rodger
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.
anand
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
hmm, I did not get it first time. I apologize for that.
anand
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
+1  A: 

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