组权限已连接到模型列表

时间:2018-07-09 18:21:48

标签: django django-models django-permissions

我的模特:

class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)

POSITIONS = (
    ("volunteer", "volunteer"),
    ("employee", "employee"),
    ("manager", "manager"),
    ("director", "director"),
    ("vet", "vet")
)
position = models.CharField(choices=POSITIONS, max_length=15)
picture = models.ImageField(blank=True, null=True)

我正在使用基于类的视图。我想根据“位置”值授予访问不同视图的权限。我找到了许多解决方案,但现在我有些困惑。做我想做的最好的方法是什么?

1 个答案:

答案 0 :(得分:1)

我会使用自定义装饰器。您可以使用@method_decorator(decorator, name='dispatch')。首先,您将在app目录中创建一个decorators.py文件。几乎发生的是方法装饰器在视图之前被调用,并将函数传递给第一个可调用对象。我们实际上所做的是将可调用对象作为位置检查进行调用,并传递position参数。然后,我们处理实际的方法装饰器部分,该部分在_method_wrapper中传递了函数参数。此时,我们就像在视图中使用_wrapper可调用对象中的request变量那样进行计算。

# decorators.py
from django.core.exceptions import PermissionDenied
from app.models import UserProfile

def position_check(position):
    def _method_wrapper(function):
        def _wrapper(request, *args, **kwargs):
            try:
                user = UserProfile.object.get(user_id=request.user.id)
            except UserProfile.DoesNotExist:
                raise PermissionDenied
            if user.position == position:
                return function(request, *args, **kwargs)
            else:
                raise PermissionDenied
        return _wrapper
    return _method_wrapper

现在在您的视图中,您将这样称呼它。

# views.py
from app.decorators import position_check
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

@method_decorator(position_check('manager'), name='dispatch')
class HomeView(TemplateView):
    template_name = "home.html"

我能看到的唯一问题是需要继承权限。我不会按照您的选择来设置您的选择。我会将实际值设置为一个数字,将选择部分设置为您的可读性,例如以下。这样一来,您就可以根据数字值设置权限,以便if user.position >= 3主管可以从管理员那里继承权限。

POSITIONS = (
    (1, "volunteer"),
    (2, "employee"),
    (3, "manager"),
    (4, "director"),
    (5, "vet")
)