🔖 Справочник — Урок 42

← К оглавлению урока

⚡ Шпаргалка по разрешениям DRF

# Минимальный кастомный permission
from rest_framework.permissions import BasePermission

class IsOwnerOrReadOnly(BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in ['GET', 'HEAD', 'OPTIONS']:
            return True
        return obj.owner == request.user

# Применение в представлении
class MyView(RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]

# Использование DjangoModelPermissions
class MyViewSet(viewsets.ModelViewSet):
    permission_classes = [DjangoModelPermissions]

Встроенные классы разрешений DRF

КлассПоведениеКогда использовать
AllowAny Доступ для всех, включая анонимов Публичные эндпоинты (регистрация, список товаров)
IsAuthenticated Только аутентифицированные пользователи Большинство защищённых API
IsAdminUser Только пользователи с is_staff=True Административные операции
IsAuthenticatedOrReadOnly Чтение — всем; запись — только аутентифицированным Публичный просмотр, приватное создание/изменение
DjangoModelPermissions Проверяет Django-разрешения модели (add/change/delete/view) Когда права настраиваются через Django Admin
DjangoObjectPermissions Права на уровне конкретного объекта с django-guardian Сложная object-level авторизация

Методы BasePermission

МетодСигнатураКогда вызываетсяВозвращает
has_permission (self, request, view) Каждый запрос к представлению True / False
has_object_permission (self, request, view, obj) При вызове get_object() True / False

SAFE_METHODS

from rest_framework.permissions import SAFE_METHODS
# SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')

class IsOwnerOrReadOnly(BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in SAFE_METHODS:  # рекомендуемый способ
            return True
        return obj.owner == request.user

Глобальная настройка разрешений

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

Переопределение на уровне представления

from rest_framework.permissions import AllowAny, IsAdminUser

class PublicView(APIView):
    permission_classes = [AllowAny]  # публичный доступ

class AdminView(APIView):
    permission_classes = [IsAdminUser]  # только администраторы

Комбинирование разрешений (DRF 3.9+)

# AND-логика (оба должны выполняться)
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]

# OR-логика (достаточно одного)
permission_classes = [IsAuthenticated | IsAdminUser]

# Сложные комбинации
permission_classes = [(IsAuthenticated & IsOwnerOrReadOnly) | IsAdminUser]

Разрешения моделей Django

РазрешениеСтрока-кодHTTP-метод в DRF
viewapp.view_bookGET, HEAD, OPTIONS
addapp.add_bookPOST
changeapp.change_bookPUT, PATCH
deleteapp.delete_bookDELETE

Управление разрешениями через Django Shell

from django.contrib.auth.models import User, Permission
from django.contrib.contenttypes.models import ContentType
from myapp.models import Book

# Получить объект разрешения
content_type = ContentType.objects.get_for_model(Book)
permission = Permission.objects.get(
    content_type=content_type,
    codename='change_book'
)

# Назначить разрешение пользователю
user = User.objects.get(username='john')
user.user_permissions.add(permission)

# Проверить разрешение
user.has_perm('myapp.change_book')  # True

Управление группами

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

# Создать группу программно
editors_group, created = Group.objects.get_or_create(name='Editors')

# Добавить разрешения в группу
editors_group.permissions.add(permission)

# Добавить пользователя в группу
user.groups.add(editors_group)

# Проверить принадлежность к группе
user.groups.filter(name='Editors').exists()  # True