次のセットアップを使用して、Django で論理的な削除を実装しています。私は内部の Django にあまり詳しくないので、遭遇する可能性のある落とし穴についてのフィードバックをいただければ幸いです。私は QuerySet をサブクラス化するのが特に苦手です。
delete
基本的な考え方は、 onの最初の呼び出しが現在の日時にMyModel
変更されるというものです。1 秒で実際にオブジェクトが削除されます。( a をキャッチするには、オブジェクトに 1 つと、オブジェクトのメソッドをバイパスできるに 1 つの 2 つのオーバーライドが必要です。) デフォルト マネージャは削除されたオブジェクトを非表示にするため、削除されたオブジェクトは消え、マネージャを介して明示的に要求する必要があります。MyModel
date_deleted
delete
delete
QuerySet
delete
deleted_objects
この設定を使用するには、 、 、および を定義してDeletionQuerySet
モデルにDeletionManager
追加する必要があります。date_deleted
objects
deleted_objects
ありがとう、
追伸、デフォルト マネージャからオブジェクトをフィルタリングするこの方法は、強く推奨されないことを忘れていました。
class DeletionQuerySet(models.query.QuerySet):
def delete(self):
prev_deleted = self.filter(date_deleted__isnull=False)
prev_deleted.actual_delete()
prev_undeleted = self.filter(date_deleted__isnull=True)
prev_undeleted.update(date_deleted=datetime.datetime.now())
def actual_delete(self):
super(DeletionQuerySet, self).delete()
class DeletionManager(models.manager.Manager):
# setting use_for_related_fields to True for a default manager ensures
# that this manager will be used for chained lookups, a la double underscore,
# and therefore that deleted Entities won't popup unexpectedly.
use_for_related_fields = True
def __init__(self, hide_deleted=False, hide_undeleted=False):
super(DeletionManager, self).__init__()
self.hide_deleted = hide_deleted
self.hide_undeleted = hide_undeleted
def get_query_set(self):
qs = DeletionQuerySet(self.model)
if self.hide_deleted:
qs = qs.filter(date_deleted__isnull=True)
if self.hide_undeleted:
qs = qs.filter(date_deleted__isnull=False)
return qs
class MyModel(models.Model):
# Your fields here...
date_deleted = models.DateTimeField(null=True)
#the first manager defined in a Model will be the Model's default manager
objects = DeletionManager(hide_deleted=True)
deleted_objects = DeletionManager(hide_undeleted=True)
def delete(self):
if self.date_deleted is None:
self.date_deleted = datetime.datetime.now()
self.save()
else:
super(Agreement, self).delete()