Добавление определенного разрешения пользователям с разными ролями в django
Я новичок в django, и я немного запутался в том, как работает разрешение, или если это то, что я должен использовать в моем случае.
Итак, у меня есть пользователь / модель:
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
ROLE_CHOICES = (
(0, ('Student')),
(1, ('Proffesor')),
(2, ('Administration'))
)
role = models.IntegerField(choices=ROLE_CHOICES, default=2)
И тогда у меня есть свои взгляды на выборах / views.py:
class MainPage(View)
class ElectionList(LoginRequiredMixin, View)
class ElectionDetail(LoginRequiredMixin, View)
#only administration can create elections
class CreateElection(LoginRequiredMixin, CreateView)
Как я могу ограничить простого пользователя (например, ученика) в создании выборов?
5 ответов
Джанго уже имеет Permission
а также Group
моделей и разрешений для каждой группы, поэтому самым чистым способом "совместимости с django" здесь будет определение "Студентов", "Профессоров" и "Администраторов" в качестве групп, настройка их разрешений (в конечном итоге добавление пользовательских при необходимости), добавление пользователей в соответствующую группу (ы), и проверьте, есть ли у вашего текущего пользователя необходимые разрешения для данного действия, используяpermission_required
декоратор или так как вы используете представление на основе классовPermissionRequiredMixin
,
Как примечание стороны: так как вы используете ints
для тебя role
значения, вы можете добавить псевдо-константы для них в вашей модели:
class User(AbstractUser):
ROLE_STUDENT = 0
ROLE_PROFESSOR = 1
ROLE_ADMINISTRATOR = 2
ROLE_CHOICES = (
(ROLE_STUDENT, 'Student'),
(ROLE_PROFESSOR, 'Professor'),
(ROLE_ADMINISTRATOR, 'Administration')
)
Таким образом, вы можете запросить / отфильтровать вашу модель, используя разумные читаемые человеком значения вместо магических чисел, то есть:
students = User.objects.filter(role=User.ROLE_STUDENT)
вместо
students = User.objects.filter(role=0)
Но если вы используете contrib.auth.models.Group
для разрешений вам может даже не понадобиться это поле, так как вы можете получить свой набор запросов от участников групп.
Ты можешь использовать UserPassesTestMixin
например.,
class LoginAndPermission(LoginRequiredMixin, UserPassesTestMixin):
def test_func(self):
return self.request.user.is_student
def get_login_url(self):
if self.request.user.is_authenticated():
# User is logged in but does not have permission
return "/permission-denied-url/"
else:
# User is not logged in
return "/login/"
class ElectionDetail(LoginAndPermission, View):
Прочитайте документацию по разрешениям и авторизации по https://docs.djangoproject.com/en/1.11/topics/auth/default
from django.contrib.auth.mixins import AccessMixin
class AddElectionPermission(AccessMixin):
raise_exception = True
permission_denied_message = 'permission deny'
def dispatch(self, request, *args, **kwargs):
if request.user.role != 0:
return self.handle_no_permission()
return super(AddElectionPermission, self).dispatch(request, *args, **kwargs)
#only administration can create elections
class CreateElection(LoginRequiredMixin, AddElectionPermission, CreateView)
Мое решение может быть альтернативой Django's Decorator. Я довольно интересен твоим вопросом.
Когда у меня есть функция в моих представлениях, и я не хочу отображать ее в группе пользователей, у меня есть файл templatetags:
from django import template
from django.contrib.auth.models import Group
register = template.Library()
@register.filter(name='has_group')
def has_group(user, group_name):
group = Group.objects.get(name=group_name)
return group in user.groups.all()
Затем в моем HTML-файле:
{% if request.user|has_group:"admin" %}
<li><a href="{% url "edited" %}">Some part</a></li>
{% endif %}
Я думаю, что в моих тегах-шаблонах возможно разрешение пользователя непосредственно в моем файле views.py, но я не знаю, как это сделать. Во всяком случае, мой метод работает очень хорошо до сих пор;)