From d0c3ba47d613dc3ac9ec29f22b6827446d46ad9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Tue, 20 Jun 2017 13:36:09 +0200 Subject: [PATCH] revoke old changes when adding an overwriting one --- src/c3nav/editor/models.py | 41 +++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/c3nav/editor/models.py b/src/c3nav/editor/models.py index bdbe571e..79ed2d3d 100644 --- a/src/c3nav/editor/models.py +++ b/src/c3nav/editor/models.py @@ -4,7 +4,7 @@ from collections import OrderedDict from django.apps import apps from django.conf import settings -from django.db import models +from django.db import models, transaction from django.db.models import Q from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor, ManyToManyDescriptor from django.urls import reverse @@ -279,19 +279,34 @@ class ChangeSet(models.Model): field_name=name, field_value=json.dumps(value, ensure_ascii=False)) def add_update(self, obj, name, value, author=None): - return self._add_value('update', obj, name, value, author) + with transaction.atomic(): + change = self._add_value('update', obj, name, value, author) + change.other_changes().filter(field_name=name).update(revoked_by=change) + return change - def add_revoke(self, obj, name, author=None): - return self._new_change(author=author, action='revoke', obj=obj, field_name=name) + def add_restore(self, obj, name, author=None): + with transaction.atomic(): + change = self._new_change(author=author, action='restore', obj=obj, field_name=name) + change.other_changes().filter(field_name=name).update(revoked_by=change) + return change def add_m2m_add(self, obj, name, value, author=None): - return self._add_value('m2m_add', obj, name, value, author) + with transaction.atomic(): + change = self._add_value('m2m_add', obj, name, value, author) + change.other_changes().filter(field_name=name, field_value=change.field_value).update(revoked_by=change) + return change def add_m2m_remove(self, obj, name, value, author=None): - return self._add_value('m2m_remove', obj, name, value, author) + with transaction.atomic(): + change = self._add_value('m2m_remove', obj, name, value, author) + change.other_changes().filter(field_name=name, field_value=change.field_value).update(revoked_by=change) + return change def add_delete(self, obj, author=None): - return self._new_change(author=author, action='delete', obj=obj) + with transaction.atomic(): + change = self._new_change(author=author, action='delete', obj=obj) + change.other_changes().update(revoked_by=change) + return change def serialize(self): return OrderedDict(( @@ -368,6 +383,18 @@ class Change(models.Model): return 'c' + str(self.pk) raise TypeError('existing_model_pk or created_object have to be set.') + @property + def other_changes(self): + """ + get queryset of other active changes on the same object + """ + qs = self.changeset.changes.filter(~Q(pk=self.pk), model_name=self.model_name, revoked_by__isnull=True) + if self.existing_object_pk is not None: + return qs.filter(existing_object_pk=self.existing_object_pk) + if self.action == 'create': + return qs.filter(created_object_id=self.pk) + return qs.filter(Q(pk=self.created_object_id) | Q(created_object_id=self.created_object_id)) + @property def obj(self) -> ModelInstanceWrapper: if self._set_object is not None: