我一直在努力让Django的URL重定向在装饰器内部工作。考虑这个简单的装饰器,确保视图的id
参数为奇数:
from django.conf import settings
from django.conf.urls import url
from django.shortcuts import redirect
from django.http import HttpResponse
from django.core.urlresolvers import reverse
from django.utils.decorators import available_attrs
from functools import wraps
def ensure_odd_id(view):
@wraps(view, assigned=available_attrs(view))
def inner(request, *args, **kwargs):
id = int(kwargs.get('id'))
if id % 2 == 0:
d = kwargs.copy()
d['id'] = str(id + 1)
return redirect(reverse(view, args=args, kwargs=d))
return view(request, *args, **kwargs)
return inner
@ensure_odd_id
def test(request, id):
return HttpResponse('test {}'.format(id))
urlpatterns = [url(r'^test/(?P<id>\d+)/$', test)]
if __name__ == '__main__':
settings.configure(DEBUG=True, ROOT_URLCONF='test')
from django.core.management import execute_from_command_line
execute_from_command_line()
如果您将此脚本保存为test.py
并使用python test.py runserver
运行,则会看到请求/test/13
不会产生错误,但请求/test/18
会产生{{1}调用NoReverseMatch
时出错,而不是重定向到reverse
:
/test/19
我觉得这与NoReverseMatch at /test/18/
Reverse for 'test.test' with arguments '()'
and keyword arguments '{'id': '19'}' not found.
0 pattern(s) tried: []
函数是未装饰的view
这一事实有关,而URL解析器只处理装饰视图。
有没有很好的方法可以在没有黑客内省的情况下重定向到装饰的view
本身?
答案 0 :(得分:0)
Django实际上在reverse
中使用了视图函数本身,所以我只需要传递装饰函数而不是原始视图:
return redirect(reverse(inner, args=args, kwargs=d))
^^^^^