Разрешение группы подключено к списку моделей
Моя модель:
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 ответ
Я бы использовал нестандартные декораторы. Вы можете использовать @method_decorator(decorator, name='dispatch')
, Сначала вы должны создать файл decorators.py в каталоге приложения. В значительной степени происходит то, что декоратор метода вызывается перед представлением и передает функцию первому вызываемому объекту. Что мы на самом деле делаем, так это делаем вызываемую функцию вызываемой как проверку позиции и передаем аргумент позиции. Затем мы обрабатываем фактическую часть декоратора метода, которая передает аргумент функции в _method_wrapper. В этот момент мы выполняем наши вычисления так же, как и в представлении с переменной request в _wrapper callable.
# 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")
)