tags:

views:

1256

answers:

3

Suppose I have a URLconf like below, and 'foo' and 'bar' are valid values for page_slug.

urlpatterns = patterns('',
    (r'^page/(?P<page_slug>.*)/', 'myapp.views.someview'),
)

Then, I could reconstruct the URLs using the below, right?

>>> from django.core.urlresolvers import reverse
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'foo'})
'/page/foo/'
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'bar'})
'/page/bar/'

But what if I change my URLconf to this?

urlpatterns = patterns('',
    (r'^foo-direct/', 'myapp.views.someview', {'page_slug': 'foo'}),
    (r'^my-bar-page/', 'myapp.views.someview', {'page_slug': 'bar'}),
)

I expected this result:

>>> from django.core.urlresolvers import reverse
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'foo'})
'/foo-direct/'
>>> reverse('myapp.views.someview', kwargs={'page_slug': 'bar'})
'/my-bar-page/'

However, this throws a NoReverseMatch exception. I suspect I'm trying to do something impossible. Any suggestions on a saner way to accomplish what I want?

Named URLs aren't an option, since I don't want other apps that link to these to need to know about the specifics of the URL structure (encapsulation and all that).

+3  A: 

Here's what we do.

urls.py has patterns like this

url(r'^(?P< datarealm >.*?)/json/someClass/(?P<object_id>.*?)/$', 'json_someClass_resource', ),

views.py as reverse calls like this

    object = SomeModel.objects.get(...)
    url= reverse('json_someClass_resource', kwargs={'object_id':object.id,'datarealm':object.datarealm.name})
S.Lott
I don't think that helps with the name collision problem.
David Berger
I originally downvoted you because of what David said, but it does look like you do actually answer Justin's question. I still think David's answer is the "better" one, but yours is a possibility.
Tyson
Maybe I didn't understand how this applied to the above on first reading. I guess it looks like it could work...but only at the cost of putting a reference to a url name in the model level. If object_1.datarealm.name='foo-direct' this will work, if object_1.datarealm.name='foo', this will not.
David Berger
Those aren't url-names -- those are values that plug into the url pattern.
S.Lott
+4  A: 

Named urls ought to be an option. Your case is highlighted in the Django reference:

http://docs.djangoproject.com/en/dev/topics/http/urls/?from=olddocs#id2

I'm not sure the designers left another work-around; they expected named urls to cover it.

May I digress about encapsulation? Thanks. There are two main reasons:

  1. Abstraction--no one wants to see the details
  2. Security--no one should see the details

As for 1, you can get a decent amount of mileage out of it in python, and Django is an excellent example. As for 2, it's an interpreted language. Either you're running it where it's written, or you're shipping off compiled .pyc files. If that's really what you're doing, then compile the url conf.

Finally, it seems less encapsulated to let other apps know about the functions than the url structure. But if you really disagree, I think you'll have to implement a more flexible reverse method yourself.

David Berger
Agreed; exporting named URLs as an API is just as "encapsulated" as exporting view function names.
Carl Meyer
A: 

You should try naming your urlconfs. Example:

urlpatterns = patterns('',
    (r'^foo-direct/', 'myapp.views.someview', {'page_slug': 'foo'}, name='foo-direct'),
    (r'^my-bar-page/', 'myapp.views.someview', {'page_slug': 'bar'}, name='bar-page'),
)

Then just edit your reverses and you should get it working.

>>> from django.core.urlresolvers import reverse
>>> reverse('foo-direct', kwargs={'page_slug': 'foo'})
'/foo-direct/'
>>> reverse('bar-page', kwargs={'page_slug': 'bar'})
'/my-bar-page/'

More info at: Django Docs

ratnushock