1
votes

In my url.py I have:

urlpatterns += patterns('',
    url(r'^tinymce/', include('tinymce.urls')),
    url(r'^', include('cms.urls')),
    url(r'^journal/', include('zinnia.urls')),
    url(r'^comments/', include('django.contrib.comments.urls')),
)

and

urlpatterns += patterns('',
    url(r'^(?P<slug>[-\w\d]+)/$', PremiumListingDetailView.as_view(), name='premium_listing'),
)

I would like to have urls for premium listing's slug at http://www.example.com/slug to show the DetailView. The page loads if I place the Premium Listing's urls before django-cms but the rest of the cms pages will not be shown, e.g. going to http://www.example.com/about will throw a 404. If I place it after the cms' include urls, going to http://www.example.com/slug will not work.

How should I structure the urls file to achieve what I need? For now, I am attaching a tilde in front of the listing urls as such: url(r'^~(?P<slug>[-\w\d]+)/$, ...) which may not be the best solution.

1
Please add the cms.urls code. - allcaps

1 Answers

1
votes

The url intended for app x is matched against a pattern of app y. The view can't match the slug and returns a 404 not found.

The pattern r'^' or r'^(?P<slug>[-\w\d]+)/$' should come last because it will catch anything. Use only one of the two because they match the same (see the cms.urls). Consider a PremiumListingDetailView object with the slug comments. At this moment it would highjack the comments app. Putting the wide matching pattern last, the important patterns will always take precedence.

The simple (and future proof) way of fixing pattern collision is making patterns unique:

url(r'^cms/', include('cms.urls')), # Added cms/

Now if the slug is not tinymce, cms, journal or comments it ends up in PremiumListingDetailView.

Alternatively you can make PremiumListingDetailView pattern unique (you did this with tilde):

url(r'^list/(?P<slug>[-\w\d]+)/$', # Added list/
    PremiumListingDetailView.as_view(), 
    name='premium_listing'),

url(r'^', include('cms.urls')), # CMS comes after.

But what if cms has a view at list/something/? The cms view won't be reached. The request will be handled by PremiumListingDetailView and the slug something won't exist resulting in a 404.

Technically you can put the PremiumListingDetailView pattern in cms.urls where you'll have fine grained control over when a cms or PremiumListingDetailView pattern is matched but the patterns are still likely to collide. This will violate the loose coupling principle. It will bite you.

Conclusion: Include apps at unique urls. Make sure each pattern in an app is unique. Wide matching patterns should come after more important patterns.