Reputation: 13580
In Understanding django.shortcuts.redirect I started a thread about reverse
and redirect_to
.
I still have some problems understanding how reverse
works when the first parameter is a string. I read https://docs.djangoproject.com/en/1.4/topics/http/shortcuts/#django.shortcuts.redirect many times and the corresponding part with reverse
. But I am still getting a NoReverseMatch
exception.
In my ROOT_URLCONF
I have
urlpatterns = patterns('',
url(r'^$', redirect_to, {'url': '/monitor/'}),
url(r'^monitor/', include('monitor.urls')),
)
In monitor.urls
I have
urlpatterns = patterns('monitor.views',
(r'^$', 'index'),
(r'^list', 'listall'),
)
and in monitor.urls
I've defined code for both functions, index
and listall
. In listall
I added the following lines:
def listall(request):
<more code goes here>
print "reversing 1 index: %s " % reverse(index)
print "reversing 2 index: %s " % reverse('index')
render_to_response("monitor/list.htmld", params)
If I visit localhost:3000/monitor/list then I can see
reversing 1 index: /monitor/
and nothing else, the second reverse
raises an exception. Why? What am I missing?
I tracked it down to djangos code django.core.urlresolvers.callable
and django.core.urlresolvers.get_mod_func
. get_mod_func
seems to expect something like "a.b", thats why in callable
the very first line returned "index" for func_name
but an empty string for mod_name
. I changed my second line to
print "reversing 2 index: %s " % reverse('monitor.views.index')
and it worked as intended. So, why do I need to call reverse
with the full module and function name (when I use strings) and the documentation doesn't? What am I missing?
Thanks
Upvotes: 1
Views: 323
Reputation: 239360
I'm not sure what part of the documentation you're hung up on, but reverse
's first parameter is some identifying method of getting to a view: it can be either a urlpattern name, a full dotted path to the view, or the view itself
So, based on your example, the first method is out because you didn't define a name for your urlpattern. Your first try, reverse(index)
worked because you literally passed it the view. Your second try, reverse('index')
, doesn't work because it need the full import context, i.e. 'monitor.views.index'
. The difference between the two is that when it's a string, Django must interpret that string to create an import for the view -- and 'index' is not enough information to determine the import path.
However, it's far, far better to just name your views if you intend on reversing them, and you should also namespace your included urlpatterns so two different apps don't end up conflicting. So in the project-level urls.py:
urlpatterns = patterns('',
url(r'^$', redirect_to, {'url': '/monitor/'}),
url(r'^monitor/', include('monitor.urls', namespace='monitor', app_name='monitor')),
)
Then, in monitor/urls.py:
urlpatterns = patterns('monitor.views',
(r'^$', 'index', name='index'),
(r'^list', 'listall', name='listall'),
)
Then, reversing is as simple as reverse('monitor:index')
.
Upvotes: 2
Reputation: 315
you should be doing something like
reverse('monitor:index')
In ROOT_URLCONF
I have
urlpatterns = patterns('',
(r'^$', redirect_to, {'url': '/monitor/'}),
(r'^monitor/', include('monitor.urls'),namespace='monitor'),
)
and in monitor.url.py
:
urlpatterns = patterns('monitor.views',
url(r'^$', 'index',name='index'),
)
for more details look at https://docs.djangoproject.com/en/1.4/topics/http/urls/#django.core.urlresolvers.reverse
Upvotes: 2