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

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

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

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

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

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

Однако, ещё до использования системы прав в 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.

Также может быть вам интересно:

Пользователи и их создание в Django - своя регистрация на сайте

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

Читать »

Пример своей консольной команды в Django проекте

Если вы работали с Django проектом, то, скорее всего, запускали команды из консоли (manage.py). В Django есть простой способ писать свои команды для управления проектом.

Читать »
Фото Python: Встроенные типы данных (list, set, dict, etc)

Python: Встроенные типы данных (list, set, dict, etc)

В Python есть множество встроенных типов данных. Их использование значительно упрощает жизнь и ускоряет разработку программных продуктов.

Фото Python: типы данных, переменные, логическое ветвление и циклы

Python: типы данных, переменные, логическое ветвление и циклы

Первая часть заметок о Python. О базовых типах, переменных, ветвлении и циклах.

Фото Как сделать свою middleware в Django (с примерами)

Как сделать свою middleware в Django (с примерами)

Middleware или "промежуточное программное обеспечение" - элегантный способ установить общие правила обработки запросов и ответов приложения. Давайте напишем парочку middleware, чтобы понять, как они работают.

Фото Как настроить отправку почты из Django

Как настроить отправку почты из Django

Письма об ошибках, отчёты на почту, восстановление паролей - всё это полезно при работе с сайтом. Django предоставляет удобный способ это сделать с минимумом настроек!

Фото Новый синтаксис старой команды with в Python 3.10

Новый синтаксис старой команды with в Python 3.10

Как же долго моё чувство прекрасного страдало… Но в Python 3.10 появился новый парсер синтаксических конструкций Python!

Фото Добавляем постраничную пагинацию на Django сайт

Добавляем постраничную пагинацию на Django сайт

На сайтах часто встречаются многостраничные объекты: список товаров, список заметок и т.д. Поэтому важно уметь добавить навигацию по страницам на Django-проекте.

Фото Новый оператор match-case в Python

Новый оператор match-case в Python

В новой версии Python (3.10) появится новый оператор. Новый оператор сопоставления по шаблону (match-case).

Фото Нет слов, одни... однострочники

Нет слов, одни... однострочники

На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.