views:

1154

answers:

3

I have a Django model with a large number of fields and 20000+ table rows. To facilitate human readable URLs and the ability to break down the large list into arbitrary sublists, I would like to have a URL that looks like this:

/browse/<name1>/<value1>/<name2>/<value2>/ .... etc ....

where 'name' maps to a model attribute and 'value' is the search criteria for that attribute. Each "name" will be treated like a category to return subsets of the model instances where the categories match.

Now, this could be handled with GET parameters, but I prefer more readable URLs for both the user's sake and the search engines. These URLs subsets will be embedded on each page that displays this model, so it seems worth the effort to make pretty URLs.

Ideally each name/value pair will be passed to the view function as a parameter named 'name1', 'name2', etc. However, I don't believe it's possible to defined named patterns via a regex's matched text. Am I wrong there?

So, it seems I need to do something like this:

urlpatterns = patterns('',
    url(r'^browse/(?:([\w]+)/([\w]+)/)+$', 'app.views.view', name="model_browse"),
)

It seems this should match any sets of two name/value pairs. While it matches it successfully, it only passes the last name/value pair as parameters to the view function. My guess is that each match is overwriting the previous match. Under the guess that the containing (?:...)+ is causing it, I tried a simple repeating pattern instead:

urlpatterns = patterns('',
    url(r'^browse/([\w]+/)+$', 'app.views.view', name="model_browse"),
)

... and got the same problem, but this time *args only includes the last matched pattern.

Is this a limitation of Django's url dispatcher, and/or Python's regex support? It seems either of these methods should work. Is there a way to achieve this without hardcoding each possible model attribute in the URL as an optional (.*) pattern?

Thanks!

+3  A: 

A possibility that you might consider is matching the entire string of possible values within the url pattern portion and pull out the specific pieces within your view. As an example:

urlpatterns = patterns('',
    url(r'^browse/(?P<match>.+)/$', 'app.views.view', name='model_browse'),
)

def view(request, match):
    pieces = match.split('/')
    # even indexed pieces are the names, odd are values
    ...

No promises about the regexp I used, but I think you understand what I mean.

(Edited to try and fix the regexp.)

Adam
Thanks, I agree this is probably the easiest way to handle the problem.
Daniel
+1  A: 

I agree with Adam, but I think the pattern in urls.py should be:

... r'^browse/(?P<match>.+)/$' ...

The '\w' will only match 'word' characters, but the '.' will match anything.

Peter Rowell
I'm terrible at regular expressions and just guessed, heh.
Adam
A: 

Same answer came to me while reading the question.

I believe model_browse view is the best way to sort the query parameters and use it as a generic router.