サイトにいくつかの制限された領域があり、そのためにlogin_required
デコレータを指定したいと思います。ただし、インクルードされたurls.pyの個々のURLごとではなく、メインのurls.pyのインクルードごとに1回実行したいと思います。
したがって、代わりに:
/private/urls.py:
(r'^profile/$', login_required(profile)),
私は線に沿って何かをします:
/urls.py
urlpatterns = patterns('',
...
(r'^private/', login_required(include('private'))),
)
残念ながら、それが機能しないことを除いて。
それは実行可能であり、実際、私はこれについて twosnippets を見つけました。
cotton による最初のスニペットは、RegexURLPattern
とRegexURLResolver
を、resolve
呼び出し中に指定されたデコレータを挿入するカスタム実装に置き換えます。
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
パラメーターを文字列にすることはできないことに注意してください。)
sjzabel による別の解決策は、私が自分で使用することになりましたが、outsidepatterns
呼び出しを適用して、次のことができるようにします。文字列で使用され、構文が少し異なります。ただし、考え方は同じです。
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'))
)
)
どちらも正常に機能しますが、私は後者の構文を好みます。
別の方法:
def decorate_url(decorator, urlconf):
'''Recreates the url object with the callback decorated'''
# urlconf autoresolves names, so callback will always be a function
return url(urlconf._regex, decorator(urlconf.callback), urlconf.default_args, urlconf.name)
def decorate_include(decorator, urlpatterns):
urls = [
decorate_url(decorator, urlconf) if not isinstance(urlconf, RegexURLResolver) else decorate_include(decorator, urlconf)
for urlconf in urlpatterns[0]
]
return (urls,) + urlpatterns[1:]
# usage
urlpatterns += patterns(
'',
url('^my-url/', decorate_include(login_required, include('app.urls'))),
)
複数のデコレータをサポートする、もう少し複雑なバージョン:
def compose_decorators(decorators, wrappee):
for wrapper in decorators:
wrappee = wrapper(wrappee)
return wrappee
def decorate_url(urlconf, *decorators):
''' Decorate a url structure with decorators '''
revdecorators = decorators[::-1] # we want the function call to read left to right
# urlconf autoresolves names, so callback will always be a function
return url(
urlconf._regex,
compose_decorators(revdecorators, urlconf.callback),
urlconf.default_args,
urlconf.name
)
def decorate_include(urlpatterns, *decorators):
''' Decorate a patterns structure with decorators '''
urls = [
decorate_url(urlconf, *decorators) if not isinstance(urlconf, RegexURLResolver) else decorate_include(urlconf, *decorators)
for urlconf in urlpatterns[0]
]
return (urls,) + urlpatterns[1:]
# usage
urlpatterns += patterns(
'',
url('^my-url/', decorate_include(include('app.urls'), login_required, decorator2)),
)
機能は問題で議論されています #25409 。 URLの大幅な修正が行われ、Django 1.10リリースが予定されています。
login_required
は、include()ではなく、呼び出し可能なビューをラップし、ソースコードを確認するためのものです。
http://code.djangoproject.com/browser/Django/tags/releases/1.1.1/Django/conf/urls/defaults.py#L9
-デフォルト(またはカスタム)を使用する簡単な方法はないと思いますlogin_required
include()を使用して、達成したいことを達成します。
これを書くと、合理的なアプローチは、次のような「ログインが必要なミドルウェア」を使用することだと思います: http://www.djangosnippets.org/snippets/1179/ そしてurls.pyでurlを飾ることを忘れてください。
あなたはdecorate_urlを使うことができます
ここを参照してください
http://github.com/vorujack/decorate_url
あなたはピップでそれをインストールすることができます
pip install decorate_url
githubでのショーの例
私はこれが非常に古い質問であることを知っているので、同じことについて疑問に思っている人のために、今非常に簡単な解決策があります。
インストールDjango-decorator-include
via pip install Django-decorator-include
。
使用方法は次のとおりです。
from Django.contrib.auth.decorators import login_required
from decorator_include import decorator_include
urlpatterns = [
path(r'^private/', decorator_include(login_required, 'private')),
]
GitHubドキュメント へのリンクは次のとおりです。
そしてここに Pypi.org へのリンクがあります