Spójrz na django-reversion
. Zapewnia kontrolę wersji dla modeli Django. Można go łatwo dodać do istniejącego projektu.
Nie stosuje podejścia "bieżącego" wskaźnika. Zamiast tego serializuje obiekt za każdym razem, gdy jest zapisywany i zapisuje go w oddzielnym modelu Version
z ogólnym kluczem obcym wskazującym na ten obiekt. (Pola relacji są domyślnie serializowane jako klucze podstawowe). Pozwala także na grupowanie Version
s w Revision
s w elastyczny sposób.
Więc można zrobić coś takiego:
- Kiedy użytkownik przesyła plik CSV, zapisz zmiany jak zwykle, ale dodać
@revision.create_on_success
dekorator do funkcji, która robi import-tak, że wszelkie zmiany zapisów dokonanych przez które Funkcja zostanie zapisana pod jedną wersją.
- Gdy użytkownik kliknie "Cofnij", po prostu przywróci ostatnią wersję.
Oto jak można to zrobić ::
@revision.create_on_success
def import_csv(request, csv):
# Old versions of all objects save()d here will
# belong to single revision.
def undo_last_csv_import(request):
# First, get latest revision saved by this user.
# (Assuming you create revisions only when user imports a CSV
# and do not version control other data.)
revision = Revision.objects.filter(user=request.user)\
.order_by('-date_created')[0]
# And revert it, delete=True means we want to delete
# any newly added records as well
revision.revert(delete=True)
Polega ona na tym, że tworzysz wersje tylko wtedy, gdy użytkownik importuje pliki CSV. Oznacza to, że jeśli planujesz również kontrolę wersji innych danych, musisz zaimplementować jakąś flagę, dzięki której możesz uzyskać rekordy, których dotyczy najnowszy import. Następnie możesz uzyskać rekord za pomocą tej flagi, pobrać najnowszą zapisaną wersję i przywrócić całą wersję, do której należy wersja. W ten sposób:
def undo_last_csv_import(request):
some_record = Record.objects.by_user(request.user).from_the_last_import()[0]
latest_saved_version_of_some_record = Version.objects.get_for_date(
some_record,
datetime.now(), # The latest saved Version at the moment.
)
# Revert all versions that belong to the same revision
# as the version we got above.
latest_saved_version_of_some_record.revision.revert()
To nie jest piękne rozwiązanie, z pewnością istnieją sposoby, aby zrobić to lepiej dzięki tej aplikacji. Polecam zajrzeć do kodu, aby lepiej zrozumieć, jak działa django-reversion
- bardzo dobrze udokumentowany, nie mógł znaleźć funkcji bez docstruowania.^_^D
(Dokumentacja jest również dobra, ale okazało się być nieco mylące dla mnie, czyli piszą Version.objects.get_for_date(your_model, date)
, gdzie your_model jest faktycznie instancja modelu).
Aktualizacja: django-powrót jest aktywnie utrzymywany, więc nie należy polegać na powyższym kodzie i lepiej sprawdzić ich wiki, jak zarządzać wersjami & wersji poza adminem Django. Na przykład komentarze wersji są już obsługiwane, co może trochę uprościć.