【问题标题】:In Django template: Check if user has permission to access view specified by name在 Django 模板中:检查用户是否有权访问由名称指定的视图
【发布时间】:2016-04-26 23:38:09
【问题描述】:

假设我有一个使用 user_passes_test 装饰器装饰的视图:

# myapp/views.py
from django.views.generic import TemplateView
from django.contrib.auth.decorators import user_passes_test

def has_perm1_or_perm2(user):
    return user.has_perm('myapp.perm1') or user.has_perm('myapp.perm2')

@user_passes_test(has_perm1_or_perm2)
class MyView(TemplateView):
    # my view code goes here

然后我将它连接到一个 URL,如下所示:

# myapp/urls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    ...,
    url(r'^myview$', views.MyView.as_view(), name='myview'),
    ...
]

如果我想在模板中放置一个指向该视图的链接,它看起来像:

<a href="{% url 'myapp:myview' %}">Check out my view!</a>

但我希望能够在模板中添加一些控制,以便仅当当前登录的用户被为视图指定的user_passes_test 函数批准时才会显示上述内容。

即我想让我的模板看起来像:

{% if check_user_has_view_permission request.user 'myapp:myview' %}
<a href="{% url 'myapp:myview' %}">Check out my view!</a>
{% else %}
Nothing to see here...
{% endif %}

我怎样才能做到这一点?

谢谢!

【问题讨论】:

  • 请注意,user_passes_test 装饰器用于过程视图。对于基于类的视图,您需要使用a mixin
  • 感谢您抽出宝贵时间发表评论。我曾认为在过去,可以装饰基于类的视图。这是 1.9 中的新事物,您需要为 CBV 使用 mixins 吗?或者它只是 CBV 上与权限相关的装饰器?还是只是建议这样做,但装饰器方法仍然有效?
  • 装饰器无法正常工作。在 Django 1.9 之前,您必须编写自己的 mixins 或装饰视图的 dispatch 方法。
  • 我认为文档表明类装饰方法有效(只要您将装饰器包装在 method_decorator 函数中):docs.djangoproject.com/es/1.9/topics/class-based-views/intro/…
  • 从您引用的链接中:“要装饰基于类的视图的每个实例,您需要装饰类定义本身。为此,您将装饰器应用于dispatch()类的方法。"

标签: django django-templates django-authentication


【解决方案1】:

你可以写一个custom template filter来做这个:

# myapp/templatetags/my_app_tags.py (probably need a better name...)
from django import template
from myapp.views import has_perm1_or_perm2

register = template.Library()

@register.filter
user_has_special_perms(user):
    return has_perm1_or_perm2(user)

然后在你的模板中:

{% load my_app_tags %}

{% if request.user|user_has_special_perms %}
<a href="{% url 'myapp:myview' %}">Check out my view!</a>
{% else %}
Nothing to see here...
{% endif %}

您也可以像这样直接检查各个权限:

{% if perms.myapp.perm1 and perms.myapp.perm2 %}

(显然这不是 DRY)。

编辑 - 如何使它更通用?

为了使这个更通用,你可以做这样的事情。首先创建某种视图到权限的映射,例如:

# myapp/views.py
VIEW_PERMISSIONS = {
    'MyView': has_perm1_or_perm2,
    # etc for other views
}

然后像这样修改模板过滤器:

from myapp.views import VIEW_PERMISSIONS

@register.filter
user_has_special_perms(user, view_class):
    perm_func = VIEW_PERMISSIONS.get(view_class, None)
    if perm_func is not None:
        return perm_func(user)
    return false

然后在模板中:

{% if request.user|user_has_special_perms:"MyView" %}

我确信不需要通过VIEW_PERMISSIONS 进行显式映射,通过对视图类本身进行某种内省,就可以实现这一点。

【讨论】:

  • 这是一个合理的开始,但它不像我在当前演示中所希望的那样普遍。特别是,在我的实际应用程序中,我将拥有数十个视图函数,每个视图函数都将具有(可能)定制的用户授权检查功能。 (视图 1 可能是 perma or permb...视图 2 可能是 perma and permc,等等。)因此,解决方案不需要为每个用户权限检查功能生成过滤器的手动步骤是必不可少的......标签需要根据其 URL 名称自动找出适用于给定视图的函数。可能吗?
  • 我已编辑回答以提供一种可能的方法来使其更通用。理想情况下,您需要对课程本身进行一些反省。
  • 我正在详细阅读这个答案 (stackoverflow.com/questions/10966493/…),看看我是否可以利用这种方法。特别是,那里的作者似乎建议使用核心权限检查装饰器的升级版本。特别是,在装饰发生之前,它会将验证函数本身作为属性附加到视图函数上。这应该可以在以后调用验证功能。
猜你喜欢
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 1970-01-01
  • 2017-01-31
  • 2012-04-06
  • 1970-01-01
  • 2011-09-07
相关资源
最近更新 更多