How do I successfully pass a function reference to Django’s reverse() function?

StackOverflow https://stackoverflow.com/questions/146522

  •  02-07-2019
  •  | 
  •  

Question

I’ve got a brand new Django project. I’ve added one minimal view function to views.py, and one URL pattern to urls.py, passing the view by function reference instead of a string:

# urls.py
# -------

# coding=utf-8

from django.conf.urls.defaults import *

from myapp import views


urlpatterns = patterns('',
    url(r'^myview/$', views.myview),
)


# views.py
----------

# coding=utf-8

from django.http import HttpResponse


def myview(request):
    return HttpResponse('MYVIEW LOL',  content_type="text/plain")

I’m trying to use reverse() to get the URL, by passing it a function reference. But I’m not getting a match, despite confirming that the view function I’m passing to reverse is the exact same view function I put in the URL pattern:

>>> from django.core.urlresolvers import reverse
>>> import urls
>>> from myapp import views

>>> urls.urlpatterns[0].callback is views.myview
True

>>> reverse(views.myview)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 254, in reverse
    *args, **kwargs)))
  File "/Library/Python/2.5/site-packages/django/core/urlresolvers.py", line 243, in reverse
    "arguments '%s' not found." % (lookup_view, args, kwargs))
NoReverseMatch: Reverse for '<function myview at 0x6fe6b0>' with arguments '()' and keyword arguments '{}' not found.

As far as I can tell from the documentation, function references should be fine in both the URL pattern and reverse().

I’m using the Django trunk, revision 9092.

Was it helpful?

Solution

Got it!! The problem is that some of the imports are of myproject.myapp.views, and some are just of myapp.views. This is confusing the Python module system enough that it no longer detects the functions as the same object. This is because your main settings.py probably has a line like:

ROOT_URLCONF = `myproject.urls`

To solve this, try using the full import in your shell session:

>>> from django.core.urlresolvers import reverse
>>> from myproject.myapp import views
>>> reverse(views.myview)
'/myview/'

Here's a log of the debugging session, for any interested future readers:

>>> from django.core import urlresolvers
>>> from myapp import myview
>>> urlresolvers.get_resolver (None).reverse_dict
{None: ([(u'myview/', [])], 'myview/$'), <function myview at 0x845d17c>: ([(u'myview/', [])], 'myview/$')}
>>> v1 = urlresolvers.get_resolver (None).reverse_dict.items ()[1][0]
>>> reverse(v1)
'/myview/'
>>> v1 is myview
False
>>> v1.__module__
'testproject.myapp.views'
>>> myview.__module__
'myapp.views'

What happens if you change the URL match to be r'^myview/$'?


Have you tried it with the view name? Something like reverse ('myapp.myview')?

Is urls.py the root URLconf, or in the myapp application? There needs to be a full path from the root to a view for it to be resolved. If that's myproject/myapp/urls.py, then in myproject/urls.py you'll need code like this:

from django.conf.urls.defaults import patterns
urlpatterns = patterns ('',
    (r'^/', 'myapp.urls'),
)

OTHER TIPS

If your two code pastes are complete, then it doesn't look like the second, which makes the actual call to reverse(), ever imports the urls module and therefor if the url mapping is ever actually achieved.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top