2009-04-13 2 views
12

Anstatt Datensätze in meiner Django-Anwendung zu löschen, möchte ich sie nur als "gelöscht" markieren und sie vor meinen aktiven Abfragen verbergen. Mein Hauptgrund dafür ist, dem Benutzer eine Undelete-Option zu geben, falls er versehentlich einen Datensatz löscht (diese Datensätze können auch für bestimmte Backend-Überwachungsnachverfolgung erforderlich sein).Wie kann ich Datensätze in Django-Modellen einfach als gelöscht markieren, anstatt sie tatsächlich zu löschen?

Es gibt viele Fremdschlüsselbeziehungen, also wann Ich markiere einen Datensatz als gelöscht. Ich müsste dieses Lösch-Flag auch auf diese Datensätze "kaskadieren". Welche Tools, bestehenden Projekte oder Methoden sollte ich verwenden?

Antwort

11

Django bietet Ihnen den genauen Mechanismus, nach dem Sie suchen.

Sie können den Manager ändern, der für den Zugriff über verwandte Objekte verwendet wird. Wenn der neue benutzerdefinierte Manager das Objekt in einem booleschen Feld filtert, wird das als inaktiv markierte Objekt nicht in Ihren Anforderungen angezeigt.

Sehen Sie hier für weitere Informationen: vor http://docs.djangoproject.com/en/dev/topics/db/managers/#using-managers-for-related-object-access

+1

aber ich glaube nicht, dass Suchen von anderen Objekten dies respektieren. Wenn Sie beispielsweise von einem verwandten Modell aus suchen, wird der Manager verwendet, der gelöschte Datensätze ignoriert. Das bedeutet, dass Datensätze, die als gelöscht markiert sind, ihre Beziehungen noch intakt haben - was wahrscheinlich nicht das ist, was Sie wollen. – fastmultiplication

+0

@fastmultiplication Durch "es wird den Manager verwenden, der gelöschte Datensätze ignoriert", meinen Sie, dass es das gelöschte Flag ignorieren wird, d. H. Es wird Datensätze löschen enthalten? Das ist das Verhalten, das ich sehe. –

+2

rechts. Die Verwendung von Managern, um zu steuern, auf welche Objekte zugegriffen werden kann, funktioniert nur, wenn Sie diese Klasse verwenden. Angenommen, Klasse A verwendet einen Manager, um "gelöschte" Objekte auszublenden, dann werden "A.Objekte" die gelöschten ausblenden. Aber wenn A zu Klasse B gehört, dann wird 'B.filter (a__name = 'smith')', alle A-Objekte durchsuchen, sogar gelöschte. – fastmultiplication

4

Nette Frage, ich habe mich gefragt, wie man das selbst effizient macht.

Ich bin nicht sicher, ob dies den Trick tun wird, aber django-reversion scheint zu tun, was Sie wollen, obwohl Sie wahrscheinlich untersuchen möchten, um zu sehen, wie es dieses Ziel erreicht, da es einige ineffiziente Möglichkeiten gibt, es zu tun.

Ein anderer Gedanke wäre, die gefürchtete boolesche Flagge auf Ihren Modellen zu haben und dann einen benutzerdefinierten Manager zu erstellen, der den Filter automatisch hinzufügt, obwohl dies nicht für Suchen über verschiedene Modelle hinweg funktionieren würde. Noch eine andere Lösung suggested here ist doppelte Modelle von allem zu haben, was wie Overkill scheint, aber kann für Sie arbeiten. Die Kommentare dort diskutieren auch verschiedene Optionen.

Ich werde hinzufügen, dass in den meisten Fällen halte ich keine dieser Lösungen die Mühe wert; Ich sauge es normalerweise einfach auf und filtere meine Suchen auf der booleschen Flagge. Es vermeidet viele Probleme, die auftreten können, wenn Sie versuchen, zu clever zu werden. Es ist ein Schmerz und nicht sehr trocken, natürlich. Eine vernünftige Lösung wäre eine Mischung aus dem benutzerdefinierten Manager, während Sie sich dessen Beschränkungen bewusst sind, wenn Sie versuchen, ein damit verbundenes Modell zu durchsuchen.

+0

+1 - Ich hatte noch nie von diesem Projekt gehört ... die Rollback-Funktion alleine ist verlockend, wenn sie wahr ist! –

+0

Django-Reversion ist cool, aber in diesem Fall ist es ein absoluter Overkill, meinst du nicht? Es geht darum, einen booleschen Zustand umzukehren und nicht zu einer von mehreren gespeicherten Versionen eines Objekts zurückzukehren. – ozan

+0

@ozan: "Ich werde hinzufügen, dass zum größten Teil halte ich keine dieser Lösungen die Mühe wert." –

3

Ich denke, mit einem booleschen "is_active" -Flag ist in Ordnung - Sie müssen nicht die Flagge auf verwandte Einträge auf der Ebene db kaskadieren, müssen Sie nur auf den Status des übergeordneten verweisen. Das passiert mit dem User-Modell von contrib.auth, denken Sie daran - einen Benutzer als nicht zu markieren is_active veranlaßt django nicht, verwandte Modelle zu durchsuchen und magischerweise versuchen, Datensätze zu deaktivieren, sondern einfach das Attribut is_active des entsprechenden Benutzers zu überprüfen verwandte Artikel.

Wenn beispielsweise jeder Benutzer viele Lesezeichen hat und Sie nicht möchten, dass die Lesezeichen eines inaktiven Benutzers sichtbar sind, stellen Sie sicher, dass bookmark.user.is_active wahr ist. Es ist unwahrscheinlich, dass ein is_active Flag auf dem Lesezeichen selbst benötigt wird.

0

Es gibt mehrere Pakete, die diese Funktionalität bereitstellen: https://www.djangopackages.com/grids/g/deletion/

Ich bin ein https://github.com/meteozond/django-permanent/ Entwicklung ersetzt es Standard-Manager und QuerySet Methoden löschen in logische Löschung zu bringen. Es überschattet Standard-Django-Löschmethoden vollständig mit einer Ausnahme - markiert Modelle, die von PermanentModel anstelle von Löschen geerbt werden, selbst wenn ihre Löschung durch Relation verursacht wird.

Verwandte Themen