問題を解決する方法の例を次に示します。
まず、permission_required の代わりに使用するデコレータ ラッパーを作成します。
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
from django.core.exceptions import PermissionDenied
from functools import wraps
from django.utils.decorators import available_attrs
def require_perms(*perms):
def decorator(view_func):
view_func.permissions = perms
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
for perm in perms:
return view_func(request, *args, **kwargs)
raise PermissionDenied()
return _wrapped_view
return decorator
次に、それを使用してビューを装飾します。
@require_perms('my_perm',)
def home(request):
.....
次に、メニュー項目に使用するタグを追加します。
from django.core.urlresolvers import resolve
def check_menu_permissions(menu_path, user):
view = resolve(menu_path)
if hasattr(view.func, "permissions"):
permissions = view.func.permissions
for perm in permissions:
if user.has_perm(perm):
return True # Yep, the user can access this url
else:
return False # Nope, the user cannot access this url
return True # or False - depending on what is the default behavior
最後に、テンプレートでメニュー ツリーを作成するときは、次のようにします。
<button href="{{ some_path }} {% if not check_menu_permissions some_path request.user %}disabled="disabled"{% endif %} />
注意: タグを使用して最後の部分をテストしていませんが、アイデアが得られたことを願っています。ここでの魔法は、デコレータの view_func にパーミッションを追加することです。そうすれば、resolve(path) を使用してこれにアクセスできます。これがパフォーマンスの面でどのように動作するかはわかりませんが、結局のところ、それは単なるアイデアです.
編集:例のバグを修正しました..