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..3a3063379 100644 --- a/openslides/assignments/models.py +++ b/openslides/assignments/models.py @@ -277,17 +277,19 @@ 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 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 diff --git a/openslides/poll/models.py b/openslides/poll/models.py index 9a1e512b9..2cbcbc96a 100644 --- a/openslides/poll/models.py +++ b/openslides/poll/models.py @@ -122,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. @@ -131,7 +131,7 @@ 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=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):