Question

I have a menu-content system in Django, where menu items are accessed by their keys and their contents through IDs. My URL mapping is:

url(r'^menu/(?P<item_key>[a-z/\-]*[a-z])/', views.menu, name='menu'),
url(r'^menu/(?P<item_key>[a-z/\-]*[a-z])/(?P<content_id>\d+)/', views.menu,\
                                               name='menu_showById'),

The first one is the base view, where the user would land after clicking on an item through the navbar. The second one is for viewing a particular content in a menu item. views.menu has an optional parameter called content_id with None as default (in which case it views the newest content).

The navbar links work fine, pointing to the menu items as http://localhost:8000/menu/some-item/sub-item. In this URL generated in the template using {% url 'data:menu' node.key %}[1], /menu/ is the view and some-item/sub-item is the item_key (example matches real use case; there are dashes and forward slashes in almost all of the item keys).

Through the base view, I click on a link generated with {% url 'data:menu_showById' menuItem.key cItem.id %} as http://localhost:8000/menu/some-item/sub-item/2/, to view the content with the ID 2. There's nothing wrong with the generated URLs, they look exactly as I want them to and the URL mapping regexes match them properly.

The problem is, while menu_showById gets the item_key parameter properly as some-item/sub-item, the second parameter content_id is never captured.

...Why?

^[1]: node is a node in the django-mptt tree structure I use to keep my menu items.

Was it helpful?

Solution

The first regex is always matching, so content_id is never picked up. Try switching the order in urls.py.

OTHER TIPS

Lesson learned: Keep your URL regexes as strict as possible. The answer by scoopseven was the most obvious solution and an important rule in defining URLs, but using it to fix something like this kinda felt like a hack to me, and more importantly made the order of my URLs into one I didn't like. So I changed the base URL from

url(r'^menu/(?P<item_key>[a-z/\-]*[a-z])/', views.menu, name='menu')

to

url(r'^menu/(?P<item_key>[a-z/\-]*[a-z])/$', views.menu, name='menu')

and now it works like a charm.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top