📖 Теория: Auth и Permissions в DRF

Краткий справочный контекст для практикума 10

⚡ Ключевые концепции

  • request.user — объект текущего пользователя, доступен в любом представлении DRF
  • perform_create(serializer) — хук сохранения объекта, позволяет добавить request.user к данным
  • get_queryset() — переопределение для фильтрации объектов по текущему пользователю
  • BasePermission — базовый класс для кастомных разрешений; методы has_permission и has_object_permission
  • Meta.permissions — пользовательские разрешения Django, регистрируются через миграции
  • dumpdata / loaddata — сериализация и восстановление данных БД
  • drf-spectacular — библиотека для генерации OpenAPI 3 схемы, Swagger UI и ReDoc

1. Извлечение пользователя из запроса

В DRF объект текущего пользователя всегда доступен через self.request.user внутри представления. Это позволяет автоматически привязывать создаваемые объекты к аутентифицированному пользователю.

perform_create — авто-привязка при создании

Метод perform_create(serializer) вызывается при успешной валидации данных перед сохранением. Его переопределение — стандартный способ добавить поле, недоступное пользователю напрямую:

def perform_create(self, serializer):
    serializer.save(customer=self.request.user)

Значение customer=self.request.user передаётся в serializer.save() и переопределяет данные из запроса. Пользователь не может подставить чужой customer.

get_queryset — фильтрация объектов по владельцу

Переопределение get_queryset() ограничивает набор объектов только теми, что принадлежат текущему пользователю:

def get_queryset(self):
    return Order.objects.filter(customer=self.request.user)

Это принципиально важно с точки зрения безопасности: без фильтрации пользователь мог бы запросить заказы других пользователей по ID.

2. Кастомные классы разрешений

DRF позволяет создавать собственные классы разрешений, наследуясь от BasePermission. Два ключевых метода:

  • has_permission(request, view) — проверяется до обращения к объекту (view-level)
  • has_object_permission(request, view, obj) — проверяется при доступе к конкретному объекту (object-level)
Важно: has_object_permission вызывается только если has_permission вернул True. Если переопределить только has_object_permission, то для list-операций проверка объектного уровня не выполняется.

Паттерн IsOwnerOrReadOnly

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

3. Пользовательские разрешения (Meta.permissions)

Django позволяет добавлять произвольные разрешения к модели через class Meta:

class Order(models.Model):
    class Meta:
        permissions = [
            ("can_view_statistics", "Can view statistics"),
        ]

После makemigrations и migrate разрешение появляется в Django Admin. Проверка в коде:

request.user.has_perm('store.can_view_statistics')

Строка состоит из: 'app_label.codename' — название приложения и кодовое имя разрешения.

4. Управление базой данных: dumpdata и loaddata

Django предоставляет команды для резервного копирования и восстановления данных:

Создание дампа

python manage.py dumpdata --indent=4 > db_backup.json

Экспортирует все данные всех приложений в формате JSON. Флаг --indent=4 делает файл читаемым. Можно ограничить конкретным приложением: dumpdata store.

Восстановление из дампа

python manage.py migrate
python manage.py loaddata db_backup.json

Сначала создаются все таблицы через миграции, затем данные загружаются из дампа.

Осторожно с ContentType: При восстановлении на новой БД могут возникнуть конфликты ContentType. Рекомендуется: python manage.py loaddata --exclude auth.permission --exclude contenttypes db_backup.json ⚠️ Проверить по документации: поведение зависит от версии Django и структуры проекта.

5. OpenAPI 3 документация через drf-spectacular

drf-spectacular — современный генератор OpenAPI 3/3.1 схем для Django REST Framework. Он читает ViewSet, Serializer, permissions и authentication settings, а затем отдаёт схему для Swagger UI, ReDoc и клиентской генерации.

Установка

pip install drf-spectacular

Подключение

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
    'drf_spectacular',
]

REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}

SPECTACULAR_SETTINGS = {
    'TITLE': 'API Documentation',
    'DESCRIPTION': 'API documentation for the project',
    'VERSION': '1.0.0',
    'SERVE_INCLUDE_SCHEMA': False,
}

Маршруты

# urls.py
from drf_spectacular.views import (
    SpectacularAPIView,
    SpectacularRedocView,
    SpectacularSwaggerView,
)

urlpatterns += [
    path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
    path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
    path('api/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
]
Практика для новых проектов: основной маршрут схемы — /api/schema/, UI — /api/docs/, ReDoc — /api/redoc/. Устаревший подход к генерации схем оставлен только в old-vs-new.html как сравнение.
← К оглавлению урока    Справочник →