PermissionDenied
Исключение PermissionDenied относится к модулю django.core.exceptions и используется для сигнализации о том, что текущий пользователь не имеет необходимых прав доступа для выполнения операции. Это исключение автоматически обрабатывается Django и приводит к возврату клиенту HTTP-ответа со статусом 403 (Forbidden). В отличие от исключения Http404, которое говорит о том, что ресурс не найден, PermissionDenied указывает на то, что ресурс существует, но недоступен для данного пользователя.
Исключение принимает один необязательный аргумент - строку с сообщением об ошибке, которая будет передана в ответ. В большинстве случаев это сообщение игнорируется, но может быть полезно для отладки или при кастомной обработке исключений. Исключение можно выбрасывать в любом месте кода, где выполняется проверка прав доступа: в представлениях, в методах моделей, в миксинах для проверки разрешений или в кастомных декораторах. Django также предоставляет встроенные механизмы для автоматического выброса этого исключения, например, декоратор permission_required и миксины для классовых представлений.
При использовании в представлениях, особенно в сочетании с декораторами, исключение PermissionDenied позволяет удобно разделять логику проверки прав и логику обработки данных. Это делает код более чистым и поддерживаемым. Также важно отметить, что исключение можно перехватывать и обрабатывать кастомным образом, например, для перенаправления на страницу входа или для логирования попыток несанкционированного доступа.
Синтаксис
from django.core.exceptions import PermissionDenied
raise PermissionDenied("Custom error message")
Пример . Использование в представлении
Проверим, имеет ли пользователь право редактировать статью, и если нет - выбросим исключение:
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from myapp.models import Article
def edit_article(request, article_id):
article = get_object_or_404(Article, id=article_id)
if request.user != article.author:
raise PermissionDenied("You are not the author of this article")
# Logic for editing the article
return render(request, "edit_article.html", {"article": article})
Пример . С декоратором permission_required
Используем встроенный декоратор для проверки наличия конкретного разрешения:
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render
@permission_required("myapp.change_article", raise_exception=True)
def publish_article(request, article_id):
# Logic for publishing the article
return render(request, "publish_article.html")
Если у пользователя нет разрешения 'myapp.change_article', декоратор автоматически выбросит исключение PermissionDenied.
Пример . В классовых представлениях
Переопределим метод dispatch или используем миксин PermissionRequiredMixin:
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views.generic import UpdateView
from django.core.exceptions import PermissionDenied
from myapp.models import Article
class ArticleUpdateView(PermissionRequiredMixin, UpdateView):
model = Article
fields = ["title", "content"]
permission_required = "myapp.change_article"
raise_exception = True
class CustomArticleDeleteView(UpdateView):
model = Article
fields = ["title"]
def dispatch(self, request, *args, **kwargs):
article = self.get_object()
if request.user != article.author:
raise PermissionDenied("Only the author can delete this article")
return super().dispatch(request, *args, **kwargs)
Пример . Кастомная обработка исключения
Переопределим обработчик для возврата кастомной страницы ошибки:
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.template import loader
def custom_permission_denied_view(request, exception=None):
template = loader.get_template("errors/403.html")
context = {"error_message": str(exception) if exception else "Access denied"}
return HttpResponse(template.render(context, request), status=403)
# In urls.py:
# handler403 = custom_permission_denied_view
Пример . В модели
Проверим права доступа в методе модели перед выполнением операции:
from django.core.exceptions import PermissionDenied
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
is_published = models.BooleanField(default=False)
def publish(self, user):
if user != self.author and not user.has_perm("myapp.can_publish_article"):
raise PermissionDenied("User cannot publish this article")
self.is_published = True
self.save()
Результат вызова метода для пользователя без прав:
from myapp.models import Article
from django.contrib.auth.models import User
article = Article.objects.get(id=1)
user = User.objects.get(username="guest")
try:
article.publish(user)
except PermissionDenied as e:
print(str(e))
Результат выполнения кода:
"User cannot publish this article"
Смотрите также
-
исключение
PermissionDenied,
которое выбрасывается при отсутствии прав доступа -
исключение
Http404,
которое выбрасывается, когда ресурс не найден -
исключение
ObjectDoesNotExist,
которое выбрасывается при отсутствии объекта в базе данных -
исключение
ValidationError,
которое выбрасывается при ошибках валидации данных