From 238b4b7f0a3457946dbcac05efa1b49de1c212c3 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Tue, 21 Mar 2017 10:33:36 +0100 Subject: [PATCH 1/3] Improving creation of ballots (fixes #3103) --- openslides/poll/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openslides/poll/models.py b/openslides/poll/models.py index 9a1e512b9..ccdeec2b8 100644 --- a/openslides/poll/models.py +++ b/openslides/poll/models.py @@ -4,6 +4,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.utils.translation import ugettext as _ +from openslides.utils.autoupdate import inform_changed_data from openslides.utils.models import MinMaxIntegerField @@ -131,7 +132,8 @@ class BasePoll(models.Model): for option_data in options_data: option = self.get_option_class()(**option_data) option.poll = self - option.save() + option.save(skip_autoupdate=True) + inform_changed_data(self.get_assignment()) def get_options(self): """ From 08bd1251a72e85a08e9ec141008263b71e887b1c Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Tue, 21 Mar 2017 11:06:05 +0100 Subject: [PATCH 2/3] More speed improvements --- openslides/agenda/models.py | 6 ++++-- openslides/agenda/views.py | 6 +++++- openslides/assignments/models.py | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/openslides/agenda/models.py b/openslides/agenda/models.py index 6896afe20..dc2f83bb0 100644 --- a/openslides/agenda/models.py +++ b/openslides/agenda/models.py @@ -331,7 +331,7 @@ class SpeakerManager(models.Manager): """ Manager for Speaker model. Provides a customized add method. """ - def add(self, user, item): + def add(self, user, item, skip_autoupdate=False): """ Customized manager method to prevent anonymous users to be on the list of speakers and that someone is twice on one list (off coming @@ -345,7 +345,9 @@ class SpeakerManager(models.Manager): _('An anonymous user can not be on lists of speakers.')) weight = (self.filter(item=item).aggregate( models.Max('weight'))['weight__max'] or 0) - return self.create(item=item, user=user, weight=weight + 1) + speaker = self.model(item=item, user=user, weight=weight + 1) + speaker.save(force_insert=True, skip_autoupdate=skip_autoupdate) + return speaker class Speaker(RESTModelMixin, models.Model): diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py index b8a8e1c82..0de3884f2 100644 --- a/openslides/agenda/views.py +++ b/openslides/agenda/views.py @@ -135,9 +135,13 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV except (ValueError, Speaker.DoesNotExist): pass else: - speaker.delete() + speaker.delete(skip_autoupdate=True) deleted_speaker_name = speaker deleted_speaker_count += 1 + # send autoupdate if speakers are deleted + if deleted_speaker_count > 0: + inform_changed_data(item) + if deleted_speaker_count > 1: message = str(deleted_speaker_count) + ' ' + _('speakers have been removed from the list of speakers.') elif deleted_speaker_count == 1: diff --git a/openslides/assignments/models.py b/openslides/assignments/models.py index ae0f81dae..a6f6d1489 100644 --- a/openslides/assignments/models.py +++ b/openslides/assignments/models.py @@ -283,11 +283,12 @@ class Assignment(RESTModelMixin, models.Model): # TODO: Try to do this in a bulk create for candidate in self.candidates: try: - Speaker.objects.add(candidate, self.agenda_item) + Speaker.objects.add(candidate, self.agenda_item, skip_autoupdate=True) except OpenSlidesError: # The Speaker is already on the list. Do nothing. # TODO: Find a smart way not to catch the error concerning AnonymousUser. pass + inform_changed_data(self.agenda_item) return poll From 0220a03350d24f3a2bcd84ca6999f264687a1649 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Fri, 24 Mar 2017 08:14:08 +0100 Subject: [PATCH 3/3] fixing test and inform_changed_data call --- openslides/assignments/models.py | 3 ++- openslides/poll/models.py | 6 ++---- tests/unit/agenda/test_views.py | 6 ++++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/openslides/assignments/models.py b/openslides/assignments/models.py index a6f6d1489..3a3063379 100644 --- a/openslides/assignments/models.py +++ b/openslides/assignments/models.py @@ -277,7 +277,8 @@ class Assignment(RESTModelMixin, models.Model): options.append({ 'candidate': related_user.user, 'weight': related_user.weight}) - poll.set_options(options) + poll.set_options(options, skip_autoupdate=True) + inform_changed_data(self) # Add all candidates to list of speakers of related agenda item # TODO: Try to do this in a bulk create diff --git a/openslides/poll/models.py b/openslides/poll/models.py index ccdeec2b8..2cbcbc96a 100644 --- a/openslides/poll/models.py +++ b/openslides/poll/models.py @@ -4,7 +4,6 @@ from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.utils.translation import ugettext as _ -from openslides.utils.autoupdate import inform_changed_data from openslides.utils.models import MinMaxIntegerField @@ -123,7 +122,7 @@ class BasePoll(models.Model): return True return False - def set_options(self, options_data=[]): + def set_options(self, options_data=[], skip_autoupdate=False): """ Adds new option objects to the poll. @@ -132,8 +131,7 @@ class BasePoll(models.Model): for option_data in options_data: option = self.get_option_class()(**option_data) option.poll = self - option.save(skip_autoupdate=True) - inform_changed_data(self.get_assignment()) + option.save(skip_autoupdate=skip_autoupdate) def get_options(self): """ diff --git a/tests/unit/agenda/test_views.py b/tests/unit/agenda/test_views.py index 76d6a4d6c..11efb7638 100644 --- a/tests/unit/agenda/test_views.py +++ b/tests/unit/agenda/test_views.py @@ -52,9 +52,10 @@ class ItemViewSetManageSpeaker(TestCase): mock_queryset = mock_speaker.objects.filter.return_value.exclude.return_value mock_queryset.get.return_value.delete.assert_called_with() + @patch('openslides.agenda.views.inform_changed_data') @patch('openslides.agenda.views.has_perm') @patch('openslides.agenda.views.Speaker') - def test_remove_someone_else(self, mock_speaker, mock_has_perm): + def test_remove_someone_else(self, mock_speaker, mock_has_perm, mock_inform_changed_data): self.request.method = 'DELETE' self.request.user = 1 self.request.data = {'speaker': '1'} @@ -63,7 +64,8 @@ class ItemViewSetManageSpeaker(TestCase): self.view_instance.manage_speaker(self.request) mock_speaker.objects.get.assert_called_with(pk=1) - mock_speaker.objects.get.return_value.delete.assert_called_with() + mock_speaker.objects.get.return_value.delete.assert_called_with(skip_autoupdate=True) + mock_inform_changed_data.assert_called_with(self.mock_item) class ItemViewSetSpeak(TestCase):