这是可行的,事实上我刚刚发现two http://djangosnippets.org/snippets/2532/ snippets http://djangosnippets.org/snippets/2607/为了这。
解决方案#1
第一个片段由cotton http://djangosnippets.org/users/cotton/替代品RegexURLPattern
and RegexURLResolver
使用在期间注入给定装饰器的自定义实现resolve
call.
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
from django.conf.urls.defaults import patterns, url, include
from django.contrib import admin
from myproject.myapp.decorators import superuser_required
class DecoratedURLPattern(RegexURLPattern):
def resolve(self, *args, **kwargs):
result = super(DecoratedURLPattern, self).resolve(*args, **kwargs)
if result:
result.func = self._decorate_with(result.func)
return result
class DecoratedRegexURLResolver(RegexURLResolver):
def resolve(self, *args, **kwargs):
result = super(DecoratedRegexURLResolver, self).resolve(*args, **kwargs)
if result:
result.func = self._decorate_with(result.func)
return result
def decorated_includes(func, includes, *args, **kwargs):
urlconf_module, app_name, namespace = includes
for item in urlconf_module:
if isinstance(item, RegexURLPattern):
item.__class__ = DecoratedURLPattern
item._decorate_with = func
elif isinstance(item, RegexURLResolver):
item.__class__ = DecoratedRegexURLResolver
item._decorate_with = func
return urlconf_module, app_name, namespace
你需要像这样使用它:
urlpatterns = patterns('',
# ...
(r'^private/', decorated_includes(login_required, include(private.urls))),
)
(注意include
此方法的参数不能是字符串。)
解决方案#2
另一种解决方案是sjzabel http://djangosnippets.org/users/sjzabel/,我最终自己使用的,被应用outside patterns
调用,因此它可以与字符串一起使用,并且语法略有不同。不过,想法是一样的。
def required(wrapping_functions,patterns_rslt):
'''
Used to require 1..n decorators in any view returned by a url tree
Usage:
urlpatterns = required(func,patterns(...))
urlpatterns = required((func,func,func),patterns(...))
Note:
Use functools.partial to pass keyword params to the required
decorators. If you need to pass args you will have to write a
wrapper function.
Example:
from functools import partial
urlpatterns = required(
partial(login_required,login_url='/accounts/login/'),
patterns(...)
)
'''
if not hasattr(wrapping_functions,'__iter__'):
wrapping_functions = (wrapping_functions,)
return [
_wrap_instance__resolve(wrapping_functions,instance)
for instance in patterns_rslt
]
def _wrap_instance__resolve(wrapping_functions,instance):
if not hasattr(instance,'resolve'): return instance
resolve = getattr(instance,'resolve')
def _wrap_func_in_returned_resolver_match(*args,**kwargs):
rslt = resolve(*args,**kwargs)
if not hasattr(rslt,'func'):return rslt
f = getattr(rslt,'func')
for _f in reversed(wrapping_functions):
# @decorate the function from inner to outter
f = _f(f)
setattr(rslt,'func',f)
return rslt
setattr(instance,'resolve',_wrap_func_in_returned_resolver_match)
return instance
像这样称呼它:
urlpatterns = patterns('',
# ...
)
urlpatterns += required(
login_required,
patterns('',
(r'^private/', include('private.urls'))
)
)
两者都工作得很好,但我更喜欢后者的语法。