在Django模板中:检查用户是否有权访问由name指定的视图

时间:2016-04-26 23:38:10

标签: django django-templates django-authentication

假设我有一个用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 %}

我怎样才能实现这一目标?

谢谢!

1 个答案:

答案 0 :(得分: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 %}

(显然这不太干)。

编辑 - 如何使其更通用?

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

# 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进行显式映射,在视图类本身上使用某种内省。