fix cache invalidation

This commit is contained in:
Laura Klünder 2017-07-07 15:32:41 +02:00
parent 45765ef135
commit e9332cfb75
3 changed files with 38 additions and 32 deletions

View file

@ -16,7 +16,6 @@ from django.utils.http import int_to_base36
from django.utils.timezone import make_naive from django.utils.timezone import make_naive
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy from django.utils.translation import ungettext_lazy
from rest_framework.exceptions import PermissionDenied
from c3nav.editor.models.changedobject import ChangedObject from c3nav.editor.models.changedobject import ChangedObject
from c3nav.editor.utils import is_created_pk from c3nav.editor.utils import is_created_pk
@ -381,19 +380,27 @@ class ChangeSet(models.Model):
def can_see(self, request): def can_see(self, request):
return self.is_author(request) return self.is_author(request)
object_changed_cache = {}
@property
def _object_changed(self):
return self.object_changed_cache.get(self.pk, None)
@_object_changed.setter
def _object_changed(self, value):
self.object_changed_cache[self.pk] = value
@contextmanager @contextmanager
def lock_to_edit(self, request=None): def lock_to_edit(self, request=None):
with transaction.atomic(): with transaction.atomic():
if self.pk is not None: if self.pk is not None:
changeset = ChangeSet.objects.select_for_update().get(pk=self.pk) changeset = ChangeSet.objects.select_for_update().get(pk=self.pk)
if request is not None and not changeset.can_edit(request):
raise PermissionDenied
self._object_changed = False self._object_changed = False
yield changeset yield changeset
if self._object_changed and request is not None: user = request.user if request is not None and request.user.is_authenticated else None
update = changeset.updates.create(user=request.user if request.user.is_authenticated else None, if self._object_changed:
objects_changed=True) update = changeset.updates.create(user=user, objects_changed=True)
changeset.last_update = update changeset.last_update = update
changeset.last_change = update changeset.last_change = update
changeset.save() changeset.save()

View file

@ -4,7 +4,6 @@ from operator import itemgetter
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from django.http import Http404 from django.http import Http404
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse from django.urls import reverse
@ -37,8 +36,8 @@ def changeset_detail(request, pk):
if request.method == 'POST': if request.method == 'POST':
restore = request.POST.get('restore') restore = request.POST.get('restore')
if restore and restore.isdigit(): if restore and restore.isdigit():
try: with changeset.lock_to_edit(request) as changeset:
with changeset.lock_to_edit(request): if changeset.can_edit(request):
try: try:
changed_object = changeset.changed_objects_set.get(pk=restore) changed_object = changeset.changed_objects_set.get(pk=restore)
except: except:
@ -48,13 +47,13 @@ def changeset_detail(request, pk):
changed_object.deleted = False changed_object.deleted = False
changed_object.save(standalone=True) changed_object.save(standalone=True)
messages.success(request, _('Object has been successfully restored.')) messages.success(request, _('Object has been successfully restored.'))
except PermissionDenied: else:
messages.error(request, _('You can not edit changes on this change set.')) messages.error(request, _('You can not edit changes on this change set.'))
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
elif request.POST.get('activate') == '1': elif request.POST.get('activate') == '1':
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if not changeset.closed: if not changeset.closed:
changeset.activate(request) changeset.activate(request)
messages.success(request, _('You activated this change set.')) messages.success(request, _('You activated this change set.'))
@ -68,7 +67,7 @@ def changeset_detail(request, pk):
messages.info(request, _('You need to log in to propose changes.')) messages.info(request, _('You need to log in to propose changes.'))
return redirect(reverse('editor.login')+'?r='+request.path) return redirect(reverse('editor.login')+'?r='+request.path)
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if not changeset.title or not changeset.description: if not changeset.title or not changeset.description:
messages.warning(request, _('You need to add a title an a description to propose this change set.')) messages.warning(request, _('You need to add a title an a description to propose this change set.'))
return redirect(reverse('editor.changesets.edit', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.edit', kwargs={'pk': changeset.pk}))
@ -82,7 +81,7 @@ def changeset_detail(request, pk):
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
elif request.POST.get('unpropose') == '1': elif request.POST.get('unpropose') == '1':
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if changeset.can_unpropose(request): if changeset.can_unpropose(request):
changeset.unpropose(request.user) changeset.unpropose(request.user)
messages.success(request, _('You unproposed your changes.')) messages.success(request, _('You unproposed your changes.'))
@ -92,7 +91,7 @@ def changeset_detail(request, pk):
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
elif request.POST.get('review') == '1': elif request.POST.get('review') == '1':
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if changeset.can_start_review(request): if changeset.can_start_review(request):
changeset.start_review(request.user) changeset.start_review(request.user)
messages.success(request, _('You are not reviewing these changes.')) messages.success(request, _('You are not reviewing these changes.'))
@ -102,7 +101,7 @@ def changeset_detail(request, pk):
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
elif request.POST.get('reject') == '1': elif request.POST.get('reject') == '1':
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if not changeset.can_end_review(request): if not changeset.can_end_review(request):
messages.error(request, _('You cannot reject these changes.')) messages.error(request, _('You cannot reject these changes.'))
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
@ -122,7 +121,7 @@ def changeset_detail(request, pk):
}) })
elif request.POST.get('unreject') == '1': elif request.POST.get('unreject') == '1':
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if not changeset.can_unreject(request): if not changeset.can_unreject(request):
messages.error(request, _('You cannot unreject these changes.')) messages.error(request, _('You cannot unreject these changes.'))
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
@ -133,7 +132,7 @@ def changeset_detail(request, pk):
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
elif request.POST.get('apply') == '1': elif request.POST.get('apply') == '1':
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if not changeset.can_end_review(request): if not changeset.can_end_review(request):
messages.error(request, _('You cannot accept and apply these changes.')) messages.error(request, _('You cannot accept and apply these changes.'))
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
@ -146,7 +145,7 @@ def changeset_detail(request, pk):
return render(request, 'editor/changeset_apply.html', {}) return render(request, 'editor/changeset_apply.html', {})
elif request.POST.get('delete') == '1': elif request.POST.get('delete') == '1':
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if not changeset.can_delete(request): if not changeset.can_delete(request):
messages.error(request, _('You cannot delete this change set.')) messages.error(request, _('You cannot delete this change set.'))
@ -352,7 +351,7 @@ def changeset_edit(request, pk):
if str(pk) != str(request.changeset.pk): if str(pk) != str(request.changeset.pk):
changeset = get_object_or_404(ChangeSet.qs_for_request(request), pk=pk) changeset = get_object_or_404(ChangeSet.qs_for_request(request), pk=pk)
with changeset.lock_to_edit() as changeset: with changeset.lock_to_edit(request) as changeset:
if not changeset.can_edit(request): if not changeset.can_edit(request):
messages.error(request, _('You cannot edit this change set.')) messages.error(request, _('You cannot edit this change set.'))
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk})) return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))

View file

@ -181,12 +181,12 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
return redirect(request.path) return redirect(request.path)
if request.POST.get('delete_confirm') == '1': if request.POST.get('delete_confirm') == '1':
try: with request.changeset.lock_to_edit(request) as changeset:
with request.changeset.lock_to_edit(request): if changeset.can_edit(request):
obj.delete() obj.delete()
except PermissionDenied: else:
messages.error(request, _('You can not edit changes on this changeset.')) messages.error(request, _('You can not edit changes on this changeset.'))
return redirect(request.path) return redirect(request.path)
messages.success(request, _('Object was successfully deleted.')) messages.success(request, _('Object was successfully deleted.'))
if model == Level: if model == Level:
if obj.on_top_of_id is not None: if obj.on_top_of_id is not None:
@ -218,8 +218,8 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
if on_top_of is not None: if on_top_of is not None:
obj.on_top_of = on_top_of obj.on_top_of = on_top_of
try: with request.changeset.lock_to_edit(request) as changeset:
with request.changeset.lock_to_edit(request): if changeset.can_edit(request):
obj.save() obj.save()
if form.redirect_slugs is not None: if form.redirect_slugs is not None:
@ -230,11 +230,11 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
obj.redirects.filter(slug=slug).delete() obj.redirects.filter(slug=slug).delete()
form.save_m2m() form.save_m2m()
except PermissionDenied: messages.success(request, _('Object was successfully saved.'))
messages.error(request, _('You can not edit changes on this changeset.')) return redirect(ctx['back_url'])
else: else:
messages.success(request, _('Object was successfully saved.')) messages.error(request, _('You can not edit changes on this changeset.'))
return redirect(ctx['back_url'])
else: else:
form = model.EditorForm(instance=obj, request=request) form = model.EditorForm(instance=obj, request=request)