2009-06-22 6 views
1

Ich verwende das folgende Setup, um weiche Löschungen in Django zu implementieren. Ich bin mit Django unter der Haube nicht sehr vertraut, daher würde ich mich über Rückmeldungen zu möglichen Problemen freuen. Ich bin besonders unbequem, wenn ich ein QuerySet ablege.Gleiche Tabelle Django ORM Soft Delete-Methode Okay?

Die Grundidee ist, dass der erste Anruf zu auf einem MyModelMyModeldate_deleted zum aktuellen datetime ändert. Eine zweite delete löscht das Objekt tatsächlich. (Das Abfangen eines delete erfordert zwei Überschreibungen, eines für das Objekt und eines für QuerySet, das die Methode delete eines Objekts umgehen kann.) Da der Standardmanager gelöschte Objekte verdeckt, verschwinden gelöschte Objekte und müssen explizit über den Manager deleted_objects angefordert werden.

dieses Setup verwenden erfordert die Definition DeletionQuerySet und DeletionManager und das Hinzufügen von date_deleted, objects und deleted_objects zu Ihrem Modell (e).

Danke,

P. S., vergessen, dass diese Methode der Filterung zu erwähnen, aus den Standardobjekten Manager strongly discouraged ist!

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() 
+3

Ein Problem wäre kaskadierende Löschungen. Diese Konfiguration dient nicht dazu, Fremdschlüssel des Löschvorgangs zu informieren. Wenn verwandte Entitäten versuchen, ihren (scheinbar gültigen) Fremdschlüssel zurück zu 'MyModel' zu folgen, erhalten sie nichts zurück. Selbst wenn der Programmierer das kaskadierende Soft-Delete implementieren würde, wie würden sich die soft-deleted Modelle auf einander beziehen, wenn die Standardmanager der Modelle gelöschte Datensätze voneinander verstecken? –

+0

Siehe meine Antwort hier. Es hat für uns gut funktioniert, verwenden Sie object_soft anstelle von Objekten in Abfragen, bei denen wir die gelöschten Modelle ausschließen möchten. Auf diese Weise können Fremdschlüssel-Lookups immer noch stattfinden. https://stackoverflow.com/questions/42123972/django-orm-soft-delete-objects-with-flag-but-still-be-able-to-look-them-up-in/47986069#47986069 –

Antwort

1

Ich denke, alles, was mit Strom im Einsatz, populär, Technologien, gibt es keine Möglichkeit, Problemdomäne Agnostiker, generische Soft Löschungen zu haben. Ich denke, es ist mehr mit historischen/Geschichte orientierten Datenbanksystemen verbunden als mit dem, was wir gewohnt sind. Ich empfehle Ihnen, django's delete nicht zu umgehen (was ein Harddelete ist). Behalten wie es ist.

Die „Löschen“, die Sie am ehesten in unserem System haben, in 90% der Fall ist, eine visuelle löschen ...

In diesem Zusammenhang versuchen Synonyme zu finden, mit für Ihre spezifischen Domain löschen Problem und tun dies von Anfang an des Projekts.

Da beschweren sich, dass ein IsVisible, IsUnpublished Ihre Anfragen (auch IsDeleted) mess up, sie beschweren sich, dass man immer vorsichtig sein müssen, um sie schließen ...

Aber das ist offensichtlich Unkenntnis der Domain Problem, wenn die Domäne hat Objekte, die unsichtbar gemacht werden können, oder unveröffentlicht werden - natürlich, wenn Sie die Liste aller Objekte abfragen, die Sie anzeigen möchten, sollten Sie von Anfang an alle Objekte abfragen, die nicht sichtbar und unveröffentlicht sind, weil dies Ihre Art ist Domain-Problem ist in einer vollständigen Form gelöst.

Prost.