Исключение ProtectedError
Исключение ProtectedError относится к модулю django.db.models
и возникает при попытке удаления объекта модели, если на него
ссылаются другие объекты через внешний ключ с установленным
параметром on_delete в значение PROTECT.
Это исключение наследуется от django.db.IntegrityError.
При возникновении исключения в атрибуте protected_objects
содержится список объектов, которые препятствуют удалению.
Синтаксис
from django.db.models import PROTECT
from django.db import models
class ParentModel(models.Model):
name = models.CharField(max_length=100)
class ChildModel(models.Model):
parent = models.ForeignKey(
ParentModel,
on_delete=PROTECT
)
title = models.CharField(max_length=100)
Пример . Возникновение исключения
Рассмотрим модели блога, где категория защищена от удаления, если на неё ссылаются статьи:
from django.db import models
from django.db.models import PROTECT
class Category(models.Model):
name = models.CharField(max_length=100)
class Article(models.Model):
title = models.CharField(max_length=100)
category = models.ForeignKey(
Category,
on_delete=PROTECT
)
content = models.TextField()
Попытка удалить категорию, к которой привязаны статьи, приведёт к возникновению исключения:
from myapp.models import Category, Article
category = Category.objects.get(id=1)
articles = Article.objects.filter(category=category)
print(f"Articles in category: {articles.count()}")
category.delete()
Результат выполнения кода:
"Articles in category: 3"
"django.db.models.deletion.ProtectedError: Cannot delete some instances of model 'Category' because they are referenced through protected foreign keys: 'Article.category'"
Пример . Обработка исключения
Исключение можно перехватить и обработать, чтобы корректно сообщить пользователю о невозможности удаления:
from django.db.models.deletion import ProtectedError
from myapp.models import Category
try:
category = Category.objects.get(name="Technology")
category.delete()
print("Category deleted successfully")
except ProtectedError as e:
print("Cannot delete category with related objects:")
for obj in e.protected_objects:
print(f"- {obj} (ID: {obj.id})")
Результат выполнения кода:
"Cannot delete category with related objects:"
"- Article: Django Basics (ID: 1)"
"- Article: Python Web (ID: 2)"
"- Article: Database Design (ID: 3)"
Пример . С несколькими защищёнными связями
Если модель имеет несколько защищённых внешних ключей, то при удалении возникнет исключение с указанием всех препятствующих объектов:
from django.db import models
from django.db.models import PROTECT
class User(models.Model):
username = models.CharField(max_length=100)
class Post(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(
User,
on_delete=PROTECT,
related_name="posts"
)
class Comment(models.Model):
text = models.TextField()
post = models.ForeignKey(
Post,
on_delete=PROTECT,
related_name="comments"
)
user = models.ForeignKey(
User,
on_delete=PROTECT,
related_name="comments"
)
Попытка удалить пользователя, у которого есть посты или комментарии, вызовет исключение:
from django.db.models.deletion import ProtectedError
from myapp.models import User
try:
user = User.objects.get(username="john_doe")
user.delete()
except ProtectedError as e:
print(f"Protected objects: {e.protected_objects}")
Результат выполнения кода:
"Protected objects: [<Post: Django Tutorial>, <Comment: Great post!>]"
Смотрите также
-
исключение
IntegrityError,
базовое исключение для всех ошибок целостности данных -
исключение
RestrictedError,
возникающее при попытке удаления с ограничениями -
исключение
DoesNotExist,
возникающее при отсутствии запрашиваемого объекта -
исключение
ObjectDoesNotExist,
базовое исключение для отсутствующих объектов модели