Django

Code

Ticket #11559 (new)

Opened 8 months ago

Last modified 2 weeks ago

urlresolvers.reverse do not work with namespaced urls and captured parameters in parent urlconf

Reported by: kmike84@gmail.com Assigned to: nobody
Milestone: Component: Core framework
Version: SVN Keywords:
Cc: calle.ba@gmail.com, kmike84@gmail.com, alexkoshelev, me@daybreaker.info, apollo13, trey@ktrl.com Triage Stage: Someday/Maybe
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 1

Description

Urlresolvers.reverse (and {% url .. %} template tag) do not work with namespaced urls and captured parameters in parent urlconf.

This works:

# In urls.py
urlpatterns = patterns('',
    (r'^(?P<username>\w+)/blog/', include('foo.urls')),
)

# In foo/urls.py
urlpatterns = patterns('foo.views',
    url(r'^index$', 'blog.index', name='blog_index'),
    url(r'^archive/$', 'blog.archive', name='blog_archive'),
)

#in some view
from django.core.urlresolvers import reverse
url = reverse('blog_index', args=['john'])

And this doesn't:

# In urls.py
urlpatterns = patterns('',
    (r'^(?P<username>\w+)/blog/', include('foo.urls', namespace='user_blogs', app_name='foo')),
)

# In foo/urls.py
urlpatterns = patterns('foo.views',
    url(r'^index$', 'blog.index', name='blog_index'),
    url(r'^archive/$', 'blog.archive', name='blog_archive'),
)

#in some view
from django.core.urlresolvers import reverse
url = reverse('user_blogs:blog_index', args=['john'], current_app='foo')

This works again:

# In urls.py
urlpatterns = patterns('',
    (r'^(?P<username>\w+)/blog/', include('foo.urls', namespace='user_blogs', app_name='foo')),
)

# In foo/urls.py
urlpatterns = patterns('foo.views',
    url(r'^index$', 'blog.index', name='blog_index'),
    url(r'^archive/$', 'blog.archive', name='blog_archive'),
)

#in some view
from django.core.urlresolvers import reverse
url = reverse('user_blogs:blog_index', current_app='foo')

# but `url` variable contains "/(?P<username>\\w+)/blog/index"

Attachments

urlresolvers.reverse.hack.patch (1.5 kB) - added by cwb on 09/26/09 03:27:59.
Hack to get parameterised parent namespace urlconfs to reverse (against 1.1)
urlresolvers.reverse.hack.diff (1.9 kB) - added by cwb on 09/26/09 03:46:19.
Maybe SVN diff against trunk with .diff extension then.. (Patch not tested on trunk)

Change History

07/27/09 11:26:58 changed by danros

  • needs_better_patch changed.
  • needs_docs changed.
  • needs_tests changed.
  • milestone set to 1.1.

I also have exactly the same issue. Bit of a let-down as I upgraded to 1.1 ahead of time in order to use namespaced urls exactly in this way!

In my example I have a 'username' argument as part of the root urlconf.

reverse('userwikis:wiki-view', kwargs={'slug':'testslug'})

'/users/(?P%3Cusername%3E%5Cw+)/wiki//testslug'

If I include the username argument:

reverse('userwikis:wiki-view', kwargs={'username':'bar','slug':'testslug'})

NoReverseMatch?: Reverse for 'wiki-view' with arguments '()' and keyword arguments '{'username': 'bar', 'slug': 'testslug'}' not found.

Seems like a fairly nasty bug for 1.1? Especially as url namespaces are one of the headline features of 1.1.

07/28/09 08:51:59 changed by russellm

  • stage changed from Unreviewed to Someday/Maybe.
  • milestone deleted.

It's arguable whether this is a bug or a feature request.

The URL namespace feature was designed to remove ambiguity in the deployment of multiple instances of an application. To that end, the namespace feature works exactly as intended.

What is being proposed here is a desire to parameterize the deployable application itself. In the example provided, the 'blog' application provides an index and archive view, but is being parameterized using the username. By contrast, the admin app is entirely self contained - it has no external parameterization, only a static 'mount point' for the URL space.

The provided URL sample doesn't require namespacing at all, since there is only one instance of the app. You would only require namespacing if there were two instances of the blog application:

/foo/<username>/blog/index
                    /archive
/bar/<username>/blog/index
                    /archive

While I can see how this could be an interesting addition to namespaced URLs, it isn't really the same problem faced by the admin app. It also opens up a bunch of questions regarding the manner in which the parameters are passed to an application - in this case, the blog requires that all views in the app take a username argument, and conversely, that it must be deployed in a tree that provides a captured username parameter. Given the potential for error here, Django would need to provide some measure of validation and protection.

So - if this is a new feature, it isn't a v1.1 blocker. However, if you choose to look at this as a bug, then it's a bug with a known workaround ("don't do that"), that doesn't break any existing code, has no potential for data loss, and with no simple solution. To that end, it's still not a v1.1 blocker at this late stage in the development cycle.

07/28/09 09:06:26 changed by kmike

If this is a new feature then existing behaviour should be documented. "Captured parameters" section is right before "Defining URL Namespaces" and the fact that they do not work together as excepted is not mentioned.

I totally agree that fixing this ticket as-is is not a trivial task and it is not in 1.1 scope.

07/29/09 05:12:19 changed by danros

I didn't include my urlconfs, which showed multiple deployments of the same app in different areas of the site.

I can confirm however that the workaround mentioned works for me. I have a requirement to include some named groups in the urlconf of one deployment of the app, and another set in another deployment. I had tried to do this by having one named group in the root urls.py and another in the application urls.py. I then multiply-included the application urls.py (with varying named groups) in the root urlconf. This doesn't work with namespaces.

Workaround is to include a different urls.py for the app depending on the named groups required. Not as elegant, but it works.

08/02/09 01:39:56 changed by alexkoshelev

  • cc changed from kmike84@gmail.com to kmike84@gmail.com, alexkoshelev.

08/03/09 22:11:39 changed by daybreaker

  • cc changed from kmike84@gmail.com, alexkoshelev to kmike84@gmail.com, alexkoshelev, me@daybreaker.info.

09/26/09 03:27:59 changed by cwb

  • attachment urlresolvers.reverse.hack.patch added.

Hack to get parameterised parent namespace urlconfs to reverse (against 1.1)

09/26/09 03:30:36 changed by cwb

  • cc changed from kmike84@gmail.com, alexkoshelev, me@daybreaker.info to calle.ba@gmail.com, kmike84@gmail.com, alexkoshelev, me@daybreaker.info.
  • needs_better_patch set to 1.

In case anyone is interested in a hack -- not a proper solution -- I've attached a patch (against 1.1). Playing around in urlresolvers.py left me almost as clueless as before about its mechanics, so I'm convinced I'm missing edge (or non-edge!) cases. I needed this to multiply up a number of app URLs with various (parameterised) prefixes, giving them different and predictable names for reversing, but found later namespaces didn't support that (either) -- something to do with only one urlconf being searched per namespace unless I misunderstood something. Thus, I abandoned them and wrote a custom url include function instead. That means this hack has hardly seen any use.

09/26/09 03:46:19 changed by cwb

  • attachment urlresolvers.reverse.hack.diff added.

Maybe SVN diff against trunk with .diff extension then.. (Patch not tested on trunk)

03/08/10 06:36:20 changed by apollo13

  • cc changed from calle.ba@gmail.com, kmike84@gmail.com, alexkoshelev, me@daybreaker.info to calle.ba@gmail.com, kmike84@gmail.com, alexkoshelev, me@daybreaker.info, apollo13.

03/08/10 08:12:08 changed by anonymous

  • cc changed from calle.ba@gmail.com, kmike84@gmail.com, alexkoshelev, me@daybreaker.info, apollo13 to calle.ba@gmail.com, kmike84@gmail.com, alexkoshelev, me@daybreaker.info, apollo13, trey@ktrl.com.

Add/Change #11559 (urlresolvers.reverse do not work with namespaced urls and captured parameters in parent urlconf)




Change Properties
Action