diff --git a/django/core/exceptions.py b/django/core/exceptions.py index 31c18ee7e1..fe4bd6d1ca 100644 --- a/django/core/exceptions.py +++ b/django/core/exceptions.py @@ -31,6 +31,10 @@ class MultipleObjectsReturned(Exception): pass +class ObjectNotUpdated(Exception): + pass + + class SuspiciousOperation(Exception): """The user did something suspicious""" diff --git a/django/db/models/base.py b/django/db/models/base.py index 89c455f313..0cdb042643 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -16,10 +16,12 @@ from django.core.exceptions import ( FieldError, MultipleObjectsReturned, ObjectDoesNotExist, + ObjectNotUpdated, ValidationError, ) from django.db import ( DJANGO_VERSION_PICKLE_KEY, + DatabaseError, connection, connections, router, @@ -47,7 +49,6 @@ from django.db.models.signals import ( pre_save, ) from django.db.models.utils import AltersData, make_model_tuple -from django.db.utils import NoRowsAffected from django.utils.deprecation import RemovedInDjango60Warning from django.utils.encoding import force_str from django.utils.hashable import make_hashable @@ -170,6 +171,20 @@ class ModelBase(type): attached_to=new_class, ), ) + new_class.add_to_class( + "NotUpdated", + subclass_exception( + "NotUpdated", + tuple( + x.NotUpdated + for x in parents + if hasattr(x, "_meta") and not x._meta.abstract + ) + or (ObjectNotUpdated, DatabaseError), + module, + attached_to=new_class, + ), + ) if base_meta and not base_meta.abstract: # Non-abstract child classes inherit some attributes from their # non-abstract parent (unless an ABC comes before it in the @@ -1112,9 +1127,11 @@ class Model(AltersData, metaclass=ModelBase): base_qs, using, pk_val, values, update_fields, forced_update ) if force_update and not updated: - raise NoRowsAffected("Forced update did not affect any rows.") + raise self.NotUpdated("Forced update did not affect any rows.") if update_fields and not updated: - raise NoRowsAffected("Save with update_fields did not affect any rows.") + raise self.NotUpdated( + "Save with update_fields did not affect any rows." + ) if not updated: if meta.order_with_respect_to: # If this is a model with an order_with_respect_to