get_absolute_url() 的 NoReverseMatch 新手问题
from food.models import *
from django.shortcuts import render_to_response, get_object_or_404
# Restaurant
def restaurant_index(request):
restaurant_list = Restaurant.objects.all()
return render_to_response('food/restaurant/index.html', {'restaurant_list': restaurant_list})
def restaurant_details(request, restaurant_id):
restaurant = get_object_or_404(Restaurant, pk=restaurant_id)
menu_list = Menu.objects.filter(restaurant=restaurant_id)
return render_to_response('food/restaurant/detail.html', {'restaurant': restaurant, 'menu_list': menu_list})
我刚开始玩Django,对get_absolute_url这个功能有点困惑。
当我尝试访问一个对象的URL时,出现了NoReverseMatch错误。这里是错误的详细信息:
$ python manage.py shell
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from food.models import *
>>> r = Restaurant.objects.get(pk=1)
>>> r
<Restaurant: East Side Marios>
>>> r.get_absolute_url()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.6/dist-packages/django/utils/functional.py", line 55, in _curried
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
File "/usr/local/lib/python2.6/dist-packages/django/db/models/base.py", line 887, in get_absolute_url
return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self, *args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/__init__.py", line 35, in inner
return reverse(bits[0], None, *bits[1:3])
File "/usr/local/lib/python2.6/dist-packages/django/core/urlresolvers.py", line 391, in reverse
*args, **kwargs)))
File "/usr/local/lib/python2.6/dist-packages/django/core/urlresolvers.py", line 337, in reverse
"arguments '%s' not found." % (lookup_view_s, args, kwargs))
NoReverseMatch: Reverse for 'food.views.restaurant_details' with arguments '()' and keyword arguments '{'restaurant_id': ['1']}' not found.
这是我目前的代码:
server/urls.py
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# ADMIN
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)),
# Restaurants
(r'^restaurants/$', 'food.views.restaurant_index'),
(r'^restaurants/(\d+)/$', 'food.views.restaurant_details'),
)
server/food/models.py
class Restaurant(models.Model):
name = models.CharField(max_length=50, unique=True)
description = models.TextField()
website = models.URLField(verify_exists=True)
def __unicode__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('food.views.restaurant_details', (), {'restaurant_id': [str(self.id)]})
server/food/views.py
餐厅列表页面显示得很好,但当然,任何餐厅的URL都是空字符串。
模板
{% if restaurant_list %}
<ul>
{% for restaurant in restaurant_list %}
<li><a href="{{ restaurant.get_absolute_url }}">{{ restaurant }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No restaurants are currently listed.</p>
{% endif %}
html
<ul>
<li><a href="">East Side Marios</a></li>
</ul>
2 个回答
3
除了Imran提供的解决方案,你可能还想了解一下命名的URL模式:
urls.py
urlpatterns = patterns('',
url(r'^restaurants/(\d+)/$', 'food.views.restaurant_details', name='restaurant_detail'),
)
restaurant_index.html
<a href="{% url restaurant_detail restaurant.id%}">{{ restaurant }}</a>
这样一来,你就不需要依赖于视图函数的名字了,而且更容易切换到通用视图。
3
(r'^restaurants/(\d+)/$', 'food.views.restaurant_details'),
你的网址模式正在把 restaurant_id
捕获为一个没有名字的组,所以你需要要么把 restaurant_id
作为位置参数提供,要么修改网址模式,让它把 restaurant_id
捕获为一个有名字的组。
把网址模式改成这样:
(r'^restaurants/(?P<restaurant_id>\d+)/$', 'food.views.restaurant_details'),
或者从 get_absolute_url
返回这个。
return ('food.views.restaurant_details', (str(self.id),), {})