1

次のセットアップを使用して、Django で論理的な削除を実装しています。私は内部の Django にあまり詳しくないので、遭遇する可能性のある落とし穴についてのフィードバックをいただければ幸いです。私は QuerySet をサブクラス化するのが特に苦手です。

delete基本的な考え方は、 onの最初の呼び出しが現在の日時にMyModel変更されるというものです。1 秒で実際にオブジェクトが削除されます。( a をキャッチするには、オブジェクトに 1 つと、オブジェクトのメソッドをバイパスできるに 1 つの 2 つのオーバーライドが必要です。) デフォルト マネージャは削除されたオブジェクトを非表示にするため、削除されたオブジェクトは消え、マネージャを介して明示的に要求する必要があります。MyModeldate_deleteddeletedeleteQuerySetdeletedeleted_objects

この設定を使用するには、 、 、および を定義してDeletionQuerySetモデルにDeletionManager追加する必要があります。date_deletedobjectsdeleted_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()
4

1 に答える 1

1

現在使用されている、人気のあるテクノロジーを使用している場合は、ドメインに依存しない一般的なソフト削除を行う方法はないと思います。私たちが使用しているものよりも、歴史的/歴史指向のデータベースシステムに関連していると思います。djangoの削除(ハード削除)を回避しないことをお勧めします。そのままにしてください。

あなたが私たちのシステムで持っている可能性が最も高い「削除」は、ケースの90%で、視覚的な削除です...

この点で、特定のドメインの問題の削除と同義語を見つけて、プロジェクトの最初からこれを実行してみてください。

IsVisible、IsUnpublished(IsDeletedでさえ)がクエリを台無しにすることを不平を言うので、彼らはあなたがそれらを含めるように常に注意しなければならないと不平を言います...

しかし、これは明らかにドメインの問題を知らないことです。ドメインに非表示にしたり、非公開にしたりできるオブジェクトがある場合は、もちろん、表示するすべてのオブジェクトのリストを照会するときは、最初からすべてを照会する必要があります。これがドメインの問題を完全な形で解決する方法であるため、表示されておらず、公開されていないオブジェクト。

乾杯。

于 2010-06-26T18:43:00.413 に答える