如何将函数引用成功传递给Django的reverse()函数?

13 投票
2 回答
6671 浏览
提问于 2025-04-11 09:19

我有一个全新的Django项目。我在views.py里添加了一个简单的视图函数,并在urls.py里添加了一个URL模式,传递视图时用的是函数引用,而不是字符串:

# 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")

我想用reverse()来获取这个URL,方法是传递一个函数引用。但是我没有找到匹配的URL,尽管我确认传给reverse的视图函数和我在URL模式里用的是同一个视图函数:

>>> 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.

根据我从文档中看到的,函数引用在URL模式和reverse()中应该都是可以的。

我使用的是Django的开发版本,修订号9092。

2 个回答

1

如果你提供的两个代码片段都是完整的,那么看起来第二个代码片段中调用reverse()的部分,并没有导入urls模块。因此,不知道这个url映射是否真的能实现。

11

明白了!!问题在于,有些导入是 myproject.myapp.views,而有些只是 myapp.views。这让Python的模块系统感到困惑,导致它无法将这些函数识别为同一个对象。这是因为你的主配置文件 settings.py 里可能有一行像这样的代码:

ROOT_URLCONF = `myproject.urls`

要解决这个问题,试着在你的命令行会话中使用完整的导入路径:

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

这里是调试会话的日志,供未来感兴趣的读者参考:

>>> 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'

如果你把URL匹配改成 r'^myview/$' 会发生什么呢?


你试过用视图名称吗?比如 reverse ('myapp.myview')

你的 urls.py 是根URL配置文件,还是在 myapp 应用里?要让视图被正确解析,需要从根目录到视图的完整路径。如果是 myproject/myapp/urls.py,那么在 myproject/urls.py 里你需要有这样的代码:

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

撰写回答