def _make_deletable(metaclass, dct):
def mark_deleted(self):
# If this is not within a managed transaction we must use commit_on_success to ensure that the object is
# only marked deleted if the updates to alerts also succeed
if transaction.is_managed():
self._mark_deleted()
else:
with transaction.commit_on_success():
self._mark_deleted()
def _mark_deleted(self):
"""Mark a record as deleted, returns nothing.
Looks up the model instance by pk, sets the not_deleted attribute
to None and saves the model instance.
Additionally marks any AlertStates referring to this item as inactive.
This is provided as a class method which takes an ID rather than as an
instance method, in order to use ._base_manager rather than .objects -- this
allows us to find the object even if it was already deleted, making this
operation idempotent rather than throwing a DoesNotExist on the second try.
"""
# Not implemented as an instance method because
# we will need to use _base_manager to ensure
# we can get at the object
from django.db.models import signals
signals.pre_delete.send(sender = self.__class__, instance = self)
if self.not_deleted:
self.not_deleted = None
self.save()
signals.post_delete.send(sender = self.__class__, instance = self)
from chroma_core.lib.job import job_log
from chroma_core.models.alert import AlertState
updated = AlertState.filter_by_item_id(self.__class__, self.id).update(active = None)
job_log.info("Lowered %d alerts while deleting %s %s" % (updated, self.__class__, self.id))
def delete(self):
raise NotImplementedError("Must use .mark_deleted on Deletable objects")
dct['objects'] = DeletableManager()
dct['delete'] = delete
dct['mark_deleted'] = mark_deleted
dct['_mark_deleted'] = _mark_deleted
# Conditional to only create the 'deleted' attribute on the immediate
# user of the metaclass, not again on subclasses.
if issubclass(dct.get('__metaclass__', type), metaclass):
# Please forgive me. Logically this would be a field called 'deleted' which would
# be True or False. Instead, it is a field called 'not_deleted' which can be
# True or None. The reason is: unique_together constraints.
dct['not_deleted'] = models.NullBooleanField(default = True)
if 'Meta' in dct:
if hasattr(dct['Meta'], 'unique_together'):
if not 'not_deleted' in dct['Meta'].unique_together:
dct['Meta'].unique_together = dct['Meta'].unique_together + ('not_deleted',)
评论列表
文章目录