diff --git a/HISTORY.rst b/HISTORY.rst index a993e20abb..7d5d0778ef 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -190,6 +190,8 @@ * Update index document types view to use the new AddRemoveView class. * Add index create and edit events. +* Allow overloading the action_add and action_remove methods + from the AddRemoveView. 3.1.11 (2019-04-XX) =================== diff --git a/docs/releases/3.2.rst b/docs/releases/3.2.rst index 83e70b564f..51e50cd2ed 100644 --- a/docs/releases/3.2.rst +++ b/docs/releases/3.2.rst @@ -222,6 +222,8 @@ Other changes * Update index document types view to use the new AddRemoveView class. * Add index create and edit events. +* Allow overloading the action_add and action_remove methods + from the AddRemoveView. Removals -------- diff --git a/mayan/apps/acls/views.py b/mayan/apps/acls/views.py index 1f7528fde8..0fa619c04e 100644 --- a/mayan/apps/acls/views.py +++ b/mayan/apps/acls/views.py @@ -162,8 +162,8 @@ class ACLListView(SingleObjectListView): class ACLPermissionsView(AddRemoveView): - action_add_method = 'permissions_add' - action_remove_method = 'permissions_remove' + main_object_method_add = 'permissions_add' + main_object_method_remove = 'permissions_remove' main_object_model = AccessControlList main_object_permission = permission_acl_edit main_object_pk_url_kwarg = 'pk' diff --git a/mayan/apps/common/generics.py b/mayan/apps/common/generics.py index afa6f3b0fb..a9bf164dfe 100644 --- a/mayan/apps/common/generics.py +++ b/mayan/apps/common/generics.py @@ -4,6 +4,7 @@ from django.conf import settings from django.contrib import messages from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ImproperlyConfigured +from django.db import transaction from django.http import HttpResponseRedirect from django.urls import reverse from django.utils.encoding import force_text @@ -178,8 +179,8 @@ class AddRemoveView(ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckM secondary_object_source_queryset = None # Main object methods to use to add and remove selections - action_add_method = None - action_remove_method = None + main_object_method_add = None + main_object_method_remove = None # If a method is not specified, use this related field to add and remove # selections @@ -196,32 +197,42 @@ class AddRemoveView(ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckM super(AddRemoveView, self).__init__(*args, **kwargs) - def action_add(self, queryset): - if self.action_add_method: - kwargs = {'queryset': queryset} - kwargs.update(self.get_action_add_extra_kwargs()) - kwargs.update(self.get_actions_extra_kwargs()) - getattr(self.main_object, self.action_add_method)(**kwargs) + def _action_add(self, queryset): + kwargs = {'queryset': queryset} + kwargs.update(self.get_action_add_extra_kwargs()) + kwargs.update(self.get_actions_extra_kwargs()) + + if hasattr(self, 'action_add'): + with transaction.atomic(): + self.action_add(**kwargs) + elif self.main_object_method_add: + getattr(self.main_object, self.main_object_method_add)(**kwargs) elif self.related_field: getattr(self.main_object, self.related_field).add(*queryset) else: raise ImproperlyConfigured( - 'View %s must be called with either an action_add_method, a ' - 'related_field.' % self.__class__.__name__ + 'View %s must be called with a main_object_method_add, a ' + 'related_field, or an action_add ' + 'method.' % self.__class__.__name__ ) - def action_remove(self, queryset): - if self.action_remove_method: - kwargs = {'queryset': queryset} - kwargs.update(self.get_action_remove_extra_kwargs()) - kwargs.update(self.get_actions_extra_kwargs()) - getattr(self.main_object, self.action_remove_method)(**kwargs) + def _action_remove(self, queryset): + kwargs = {'queryset': queryset} + kwargs.update(self.get_action_remove_extra_kwargs()) + kwargs.update(self.get_actions_extra_kwargs()) + + if hasattr(self, 'action_remove'): + with transaction.atomic(): + self.action_remove(**kwargs) + elif self.main_object_method_remove: + getattr(self.main_object, self.main_object_method_remove)(**kwargs) elif self.related_field: getattr(self.main_object, self.related_field).remove(*queryset) else: raise ImproperlyConfigured( - 'View %s must be called with either an action_remove_method, a ' - 'related_field.' % self.__class__.__name__ + 'View %s must be called with a main_object_method_remove, a ' + 'related_field, or an action_remove ' + 'method.' % self.__class__.__name__ ) def dispatch(self, request, *args, **kwargs): @@ -237,7 +248,7 @@ class AddRemoveView(ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckM pk__in=forms['form_available'].cleaned_data['selection'] ) - self.action_add(queryset=selection_add) + self._action_add(queryset=selection_add) if 'added-remove_all' in self.request.POST: selection_remove = self.get_list_added_queryset() @@ -246,7 +257,7 @@ class AddRemoveView(ExternalObjectMixin, ExtraContextMixin, ViewPermissionCheckM pk__in=forms['form_added'].cleaned_data['selection'] ) - self.action_remove(queryset=selection_remove) + self._action_remove(queryset=selection_remove) return super(AddRemoveView, self).forms_valid(forms=forms) diff --git a/mayan/apps/permissions/views.py b/mayan/apps/permissions/views.py index 6b1ab2b33b..afea0a3779 100644 --- a/mayan/apps/permissions/views.py +++ b/mayan/apps/permissions/views.py @@ -22,8 +22,8 @@ from .permissions import ( class GroupRolesView(AddRemoveView): - action_add_method = 'roles_add' - action_remove_method = 'roles_remove' + main_object_method_add = 'roles_add' + main_object_method_remove = 'roles_remove' main_object_model = Group main_object_permission = permission_group_edit main_object_pk_url_kwarg = 'pk' @@ -69,8 +69,8 @@ class RoleEditView(SingleObjectEditView): class SetupRoleMembersView(AddRemoveView): - action_add_method = 'groups_add' - action_remove_method = 'groups_remove' + main_object_method_add = 'groups_add' + main_object_method_remove = 'groups_remove' main_object_model = Role main_object_permission = permission_role_edit main_object_pk_url_kwarg = 'pk' @@ -95,8 +95,8 @@ class SetupRoleMembersView(AddRemoveView): class SetupRolePermissionsView(AddRemoveView): - action_add_method = 'permissions_add' - action_remove_method = 'permissions_remove' + main_object_method_add = 'permissions_add' + main_object_method_remove = 'permissions_remove' grouped = True main_object_model = Role main_object_permission = permission_role_edit diff --git a/mayan/apps/user_management/views.py b/mayan/apps/user_management/views.py index 0bdaa84b3f..9c3a795457 100644 --- a/mayan/apps/user_management/views.py +++ b/mayan/apps/user_management/views.py @@ -126,8 +126,8 @@ class GroupListView(SingleObjectListView): class GroupUsersView(AddRemoveView): - action_add_method = 'users_add' - action_remove_method = 'users_remove' + main_object_method_add = 'users_add' + main_object_method_remove = 'users_remove' main_object_model = Group main_object_permission = permission_group_edit main_object_pk_url_kwarg = 'pk' @@ -260,8 +260,8 @@ class UserEditView(SingleObjectEditView): class UserGroupsView(AddRemoveView): - action_add_method = 'groups_add' - action_remove_method = 'groups_remove' + main_object_method_add = 'groups_add' + main_object_method_remove = 'groups_remove' main_object_permission = permission_user_edit main_object_source_queryset = get_user_queryset() main_object_pk_url_kwarg = 'pk'