Программы
Разграничение прав доступа на Django сайте

Разграничение прав доступа на Django сайте

Почти на любом веб-сайте необходимо разделять пользователей на группы и предоставлять им разные возможности. В Django есть довольно серьёзная система прав доступа для пользователей - давайте её рассмотрим!

Мы уже разобрали, как добавить логин на Django сайт, а также регистрацию. Теперь пришла пора разделять и властвовать - каждому пользователю дать свои возможности на сайте, чтобы каждый мог причинять пользу по мере возможностей/прав.

Если вы добавили в админ панель свою модель пользователя, либо же используете стандартную, то на странице редактирования пользователя можете увидеть настройку прав через группы пользователей ("Groups"/"Группы") или напрямую ("User permissions"/"Права пользователя").

Изображение Python 3.11. Что нового?

Делим на анонимов и залогиненных

Однако, ещё до использования системы прав в Django, уже можно настроить доступ, например, для авторизованных пользователей и анонимов. Для этого можно воспользоваться объектом пользователя из request. Так мы можем разделить логику - для зарегистрированных пользователей выполнить одни действия, для остальных - другие:

def some_view(request):
    if request.user.is_anonymous:
        ...
    else:
        ...

Или же, если нужно предоставить доступ ко view только для авторизованных пользователей, а прочих отправить на страницу логина (LOGIN_URL), что пользуемся декоратором login_required:

from django.contrib.auth.decorators import login_required


@login_required
def some_view(request):
    ...

Если же вы пользуетесь class-based views, то декорировать надо метод dispatch. А login_required обёрнуть в декоратор method_decorator:

from django.contrib.auth.decorators import login_required
from django.views.generic import DetailView
from django.utils.decorators import method_decorator


class SomeView(DetailView):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        super().dispatch(request, *args, **kwargs)

Группы пользователей и права в Django

Завершив разделение на залогиненных и анонимов, можно перейти к разделению пользователей по их правам и группам.

Настройка через группы позволит устанавливать и менять права сразу всем пользователям, добавленным в неё, а прямая - на конкретного. В сущности, сами права у них не отличаются:

  • Право на добавление объекта модели: 'имя-приложения.add_имя-модели'
  • Право на редактирование объекта модели: 'имя-приложения.change_имя-модели'
  • Право на удаление объекта модели: 'имя-приложения.delete_имя-модели'
  • Право на просмотр объектов модели: 'имя-приложения.view_имя-модели'

То есть на каждую модель подключённого приложения создаётся набор прав. Проверять же их можно в коде с помощью has_perm - для одного права доступа, has_perms - для нескольких:

def change_tags(request):
    if request.user.has_perm('tags.add_tag'):
        ...
    if request.user.has_perms(['tags.add_tag', 'tags.change_tag']):
        ...

Или же с помощью декоратора:

from django.contrib.auth.decorators import permission_required


@permission_required('tags.add_tag')
def create_tag(request):
    pass


@permission_required(['tags.delete_tag', 'tags.change_tag'])
def modify_tag(request):
    pass

Также можно добавлять пользователя в группу динамически из нашего кода. Например, достигнув определённого рейтинга (или времени регистрации на сайте), пользователь может быть добавлен в какую-нибудь группу:

from django.contrib.auth.models import Group


class UserModel(...):
    def rating_up(self):
        ...
        adept_group = Group.objects.get(name='Адепт')
        if self.rating == 50 and self.groups.filter(id=adept_group.id).exists():
            self.groups.add(adept_group)

Также можно добавлять права непосредственно пользователю. Для этого надо получить объект самого права, а потом добавить в user_permissions:

from django.contrib.auth.models import Permission
from user.models import User

perm = Permission.objects.get(content_type__app_label='tag', content_type__model='tag', codename='add_tag')
user = User.objects.get(usename='gosha')
user.user_permissions.add(perm)

Аналогично можно добавить права группе:

from django.contrib.auth.models import Group
from django.contrib.auth.models import Permission

adept_group = Group.objects.get(name='Адепт')
perm = Permission.objects.get(content_type__app_label='tag', content_type__model='tag', codename='add_tag')
adept_group.permissions.add(perm)

Если вдруг вам не хватает стандартных прав доступа, вы можете создать свою для какой-то модели:

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get(app_label='app_name', model='model_name')
permission = Permission.objects.create(
    codename='can_masscreate_tag',
    name='Can mass create Tag',
    content_type=content_type
)

Или же в самой модели в Meta:

class Tag(models.Model):
    ...

    class Meta:
        permissions = (
            ("can_masscreate_tag", "Can mass create Tag"),
        )

Пожалуй, на этом тему прав доступа можно считать закрытой.

Если интересно, что дальше - читайте рубрику Django.