在不调用它们的情况下找到 Django URL 所需的权限? [英] Find the required permissions of Django URLs without calling them?

查看:27
本文介绍了在不调用它们的情况下找到 Django URL 所需的权限?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 Django 应用程序当前具有受permission_required()"函数保护的 URL.

My Django app currently has URLs which are protected by 'permission_required()' functions.

这个函数以三种不同的方式被调用.

This function is called in three different ways.

  1. 作为 views.py 中的装饰器,带有硬编码参数.
  2. 作为一个普通函数,带有自动生成的参数,在自定义的基于类的通用视图中.
  3. 作为使用硬编码参数调用 urls.py 中的视图的函数.

我现在正在向应用程序添加一个菜单系统,我需要让菜单条目反映用户是否有权请求每个菜单条目的 URL.(通过灰显或隐藏所述条目.)

I'm now adding a menu system to the app, and I need to make menu entries reflect whether the user has permission to request the URL of each menu entry. (Either by greying-out or hiding said entries.)

是否有一种方法可以在不请求 URL 的情况下查询 URL 所需的权限?

Is there a way of query the permissions required to a URL without requesting the URL?

到目前为止,我想到的唯一解决方案是用无参数的menu_permssion_required()"装饰器替换装饰器,并将所有权限硬编码到 Python 结构中.这似乎是一种倒退,因为我自定义的基于类的通用视图已经自动生成了它们所需的权限.

The only solution I've thought of so far is to replace the decorator with a parameterless 'menu_permssion_required()' decorator and hardcode all of the permissions into a Python structure. This seems like a step backwards, as my custom Class Based Generic Views already autogenerate their required permissions.

关于如何制作反映当前用户 URL 权限的菜单系统有什么建议吗?

Any suggestions on how to make a menu system which reflects URL permissions for the current user?

推荐答案

以下是如何解决您的问题的示例:

Here is an example of how to solve your problem:

首先,创建一个装饰器包装器来代替permission_required:

First, Create a decorator wrapper to use instead of 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

然后,用它来装饰你的视图:

Then, use it to decorate your views:

@require_perms('my_perm',)
def home(request):
.....

然后,为您的菜单项添加一个标签:

Then, add a tag to use for your menu items:

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

最后,在您的模板中,构建菜单树时:

And finally, in your templates, when building the menu tree:

<button href="{{ some_path }} {% if not check_menu_permissions some_path request.user %}disabled="disabled"{% endif %} />

注意我还没有用标签测试最后一部分,但我希望你明白了.这里的神奇之处是在装饰器中为 view_func 添加权限,然后您可以使用 resolve(path) 访问它.我不确定这在性能方面会如何表现,但毕竟这只是一个想法.

N.B. I've not tested the last part with the tag, but I hope you got the idea. The magic thing here is to add the permissions to the view_func in the decorator, and then you can access this using resolve(path). I'm not sure how this will behave in terms of performance, but after all that's just an idea.

编辑:刚刚修复了示例中的一个错误..

EDIT: Just fixed a bug in the example..

这篇关于在不调用它们的情况下找到 Django URL 所需的权限?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆