How do I use django.core.urlresolvers.reverse with a function reference instead of a named URL pattern?
Question
In my urls.py
file, I have:
from myapp import views
...
(r'^categories/$', views.categories)
Where categories
is a view function inside myapp/views.py
. No other URLconf lines reference views.categories
.
In a unit test file, I’m trying to grab this URL using django.core.urlresolvers.reverse()
, instead of just copying '/categories/' (DRY and all that). So, I have:
from django.core.urlresolvers import reverse
from myapp import views
...
url = reverse(views.categories)
When I run my tests, I get a NoReverseMatch
error:
NoReverseMatch: Reverse for '<function categories at 0x1082f30>' with arguments '()' and keyword arguments '{}' not found.
It matches just fine if I make the URL pattern a named pattern, like this:
url(r'^categories/$', views.categories, 'myapp-categories')
And use the pattern name to match it:
url = reverse('myapp-categories')
But as far as I can tell from the reverse
documentation, I shouldn’t need to make it a named URL pattern just to use reverse
.
Any ideas what I’m doing wrong?
Solution 2
After futher investigation, turns out it was an issue with how I was importing the views module:
How do I successfully pass a function reference to Django’s reverse() function?
Thanks for the help though, guys: you inspired me to look at it properly.
OTHER TIPS
Jack M.'s example is nearly correct.
It needs to be a url function, not a tuple, if you want to use named urls.
url(r'^no_monkeys/$', 'views.noMonkeys', {}, "no-monkeys"),
This does work, and all the code that you've pasted is correct and works fine (I just copied it into a clean test/project app and it reversed the URL without any problem). So there's something else going on here that you haven't showed us. Simplify down to the bare-bones basics until it works, then start adding complexity back in and see where it's breaking.
Also, you can do "./manage.py shell" and then interactively import the reverse function and your view function and try the reverse. That'll remove the test setup as a possible cause.
The reverse function actually uses the "name" of the URL. This is defined like so:
urlpatterns = patterns('',
(r'^no_monkeys/$', 'views.noMonkeys', {}, "no-monkeys"),
(r'^admin/(.*)', admin.site.root),
)
Now you would call reverse with the string "no-monkeys" to get the correct url.
Ninja Edit: Here is a link to the django docs on the subject.