Добавление определенного разрешения пользователям с разными ролями в 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, но я не знаю, как это сделать. Во всяком случае, мой метод работает очень хорошо до сих пор;)

Другие вопросы по тегам