我的Django应用程序目前具有由“permission_required()”功能保护的URL。
该功能被称为三种不同的方式。
- 作为views.py一个装饰,用硬编码参数。
- 作为一个普通的功能,具有自动生成的参数,在基于自定义类通用视图。
- 作为一个函数调用意见urls.py,用硬编码参数。
现在我加入了菜单系统的应用程序,我需要做的菜单项反映用户是否有权要求每个菜单项的URL。 (通过变灰出或隐藏所述条目。)
是否有查询的方式需要一个URL的权限,而无需请求URL?
到目前为止,我认为唯一的解决办法是用“menu_permssion_required()”装饰一个参数的更换装饰与硬编码的所有权限到一个Python结构。 这似乎是一个倒退,因为基于我的自定义类通用视图自动生成已经他们所需的权限。
如何使这反映URL的权限当前用户的菜单系统有什么建议?
下面是如何解决你的问题的例子:
首先,创建一个装饰包装,而不是使用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的装饰,然后你可以访问此使用的决心(路径)。 我不知道这将如何在性能方面的表现,但毕竟这只是一个想法。
编辑 :只是固定在例如一个bug ..
是否有查询的方式需要一个URL的权限,而无需请求URL?
User.has_perm()和User.has_module_perms()
如何使这反映URL的权限当前用户的菜单系统有什么建议?
我真的很喜欢这个问题,因为它涉及的人,使Django的网站,所以我觉得很重要。 我已经通过我自己,甚至编码的菜单中的“系统”在我的第一个Django项目在2008年回来,但从那时起,我试过Pinax和的(这么多)的事情,我从他们的榜样项目中吸取的一个是,它是完全不必要的膨胀。
所以,我没有意见,我会就如何使一个菜单中的“系统”,尊重请求用户权限支持。
我对如何做一个简单的菜单,尊重请求用户权限的建议,这样可能不是完全无关。
只是让你在普通的HTML菜单 ,它不喜欢它会如此频繁,它必须产生改变。 这也将让您的Python代码更简单。
添加到settings.TEMPLATE_CONTEXT_PROCESSORS
: 'django.core.context_processors.PermWrapper'
使用{{ perms }} proxy
到User.has_perms。
例:
{% if perms.auth %}
<li class="divider"></li>
{% if perms.auth.change_user %}
<li>
<a href="{% url admin:auth_user_changelist %}">{% trans 'Users' %}</a>
</li>
{% endif %}
{% if perms.auth.change_group %}
<li>
<a href="{% url admin:auth_group_changelist %}">{% trans 'User groups' %}</a>
</li>
{% endif %}
{% endif %}
{# etc, etc #}
这就是我如何保持导航简单 , 愚蠢 , 闪开 。 而且我一直有一个自动完成从菜单不远允许用户导航到任何详细信息页面容易。 所以,这是我所知道的关于在Django项目中导航,我渴望去阅读其他的答案!
我也有类似的问题,但它去得更深一些。 而不是仅仅权限的,我也想基础上加盖的用户其他测试(即is_staff
,或user.units.count() > 1
)。 在视图中复制这些和模板似乎容易出错。
您可以内省一个视图对象,并看到所有的装饰包裹它,并制定出它们是否检查(在我的情况:在第一个参数我倒是u
或user
)。 如果他们都通过,则允许渲染的链接。
获取包装功能的所有装饰描述更详细一点的技术。 你可以发现,这个包装成一个方便的更换为应用程序{% url %}
在Django的菜单 。