tags:

views:

1891

answers:

4

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?

A: 

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.

Jack M.
Sure, it seems to work fine if I use named URL patterns. But I think it should work just with a function reference.As a side note, I think you need to use the URL function instead of just a tuple to create named URL pattern i.e. url(r'^no_monkeys/$', 'views.noMonkeys', {}, "no-monkeys")
Paul D. Waite
Yes, you need to call `the url()` function to use named URLs, as I have stated. http://stackoverflow.com/questions/134629/how-do-i-use-djangocoreurlresolversreverse-with-a-function-reference-instead-of#136721
camflan
And, `name` is a keyword argument and must be signed as such.
camflan
A: 

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.

Carl Meyer
You’re quite right: I’m a bit new to programming, so often I forget the proper troubleshooting steps like that. It’s weird though, I’ve created a new, empty one-app project, pasted the code in, and I can’t get it working there either. I’ll fiddle some more.
Paul D. Waite
+1  A: 

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"),
camflan
A: 

After futher investigation, turns out it was an issue with how I was importing the views module:

http://stackoverflow.com/questions/146522/how-do-i-successfully-pass-a-function-reference-to-djangos-reverse-function

Thanks for the help though, guys: you inspired me to look at it properly.

Paul D. Waite