def really_delete_selected(self, request, queryset): deleted_count = 0 protected_count = 0 # Check that the user has delete permission for the actual model if not self.has_delete_permission(request): raise PermissionDenied for obj in queryset: try: obj.delete() deleted_count += 1 except ProtectedError: protected_count += 1 if deleted_count: messages.add_message(request, messages.INFO, _("Successfully deleted %(count)d %(items)s.") % { "count": deleted_count, "items": model_ngettext(self.opts, deleted_count) }) if protected_count: # TODO More informative feedback, possibly with an intermediate screen. Compare messages on trying to delete one object. messages.add_message(request, messages.ERROR, _( "%(count)d %(items)s not deleted, because that would require deleting protected related objects.") % { "count": protected_count, "items": model_ngettext(self.opts, protected_count) })
def undelete_selected(self, request, queryset): """ Admin action to undelete objects in bulk with confirmation. """ if not self.has_delete_permission(request): raise PermissionDenied assert hasattr(queryset, 'undelete') # Remove not deleted item from queryset queryset = queryset.filter(deleted=True) # Undeletion confirmed if request.POST.get('post'): n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) self.log_undeletion(request, obj, obj_display) queryset.undelete() if django.VERSION[1] <= 4: self.message_user( request, _("Successfully undeleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, ) else: self.message_user( request, _("Successfully undeleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, messages.SUCCESS, ) # Return None to display the change list page again. return None opts = self.model._meta if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) title = _("Are you sure?") context = { 'title': title, 'objects_name': objects_name, 'queryset': queryset, "opts": opts, "app_label": opts.app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } return TemplateResponse( request, self.undelete_selected_confirmation_template, context, current_app=self.admin_site.name, )
def clear_api_cache(self, request, queryset): for instance in queryset: instance.api(clear=True) count = len(queryset) message = 'Cleared API cache for {count} {items}.'.format( count=count, items=model_ngettext(self.opts, count)) self.message_user(request, message)
def promote_to_ra(self, request, queryset): from django.contrib import messages from django.contrib.admin import helpers from django.contrib.admin.utils import model_ngettext if request.POST.get('post'): n = queryset.count() if n: for org in queryset.all(): org.promote_to_registration_authority() self.message_user(request, _("Successfully promoted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None context = dict( self.admin_site.each_context(request), title=_("Are you sure?"), queryset=queryset, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, media=self.media, opts=self.model._meta ) request.current_app = self.admin_site.name # Display the confirmation page from django.template.response import TemplateResponse return TemplateResponse(request, ["admin/promote_org_to_ra.html"], context)
def make_dirty(self, request, queryset): rows_updated = queryset.filter(publisher_state=self.model.PUBLISHER_STATE_PUBLISHED) \ .update(publisher_state=self.model.PUBLISHER_STATE_CHANGED) message = _('{count} {verbose_name} marked as changed.').format( count=rows_updated, verbose_name=model_ngettext(self.opts, rows_updated) ) self.message_user(request, message, messages.SUCCESS)
def delete_selected(self, request, queryset): if not self.has_delete_permission(request): raise PermissionDenied hearing_count = queryset.count() if hearing_count: for hearing in queryset: hearing.soft_delete() self.message_user(request, _('Successfully deleted %(count)d %(items)s.') % { 'count': hearing_count, 'items': model_ngettext(self.opts, hearing_count) })
def _set_objects_active(self, request, queryset, active): """ Sets the 'is_active' property of each item in ``queryset`` to ``active`` and reports success to the user. """ # We call save on each object instead of using queryset.update to allow for custom save methods and hooks. count = 0 for obj in queryset.select_for_update(): obj.is_active = active obj.save(update_fields=['is_active']) count += 1 self.message_user(request, _("Successfully %(prefix)sactivated %(count)d %(items)s.") % { "prefix": "" if active else "de", "count": count, "items": model_ngettext(self.opts, count) })
def reset_to_pending(modeladmin, request, queryset): """ Default action to reset selected object's status to pending """ ip_count = moderate_selected(modeladmin, request, queryset, PENDING_STATUS) if ip_count: modeladmin.message_user( request, _("Successfully reset status of %(count)d %(items)s.") % { 'count': ip_count, 'items': model_ngettext(modeladmin.opts, ip_count) } ) return None
def censor_selected(modeladmin, request, queryset): """ Censor the selected submissions, with confirmation interstitial. Largely stolen from django.contrib.admin.actions.delete_selected """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): censored_url = request.POST.get('censored_url', None) n = queryset.count() if n: for obj in queryset: obj.censor(url=censored_url) obj_display = force_unicode(obj) modeladmin.message_user(request, _("Censored %(item)s") % { "item": obj_display }) modeladmin.message_user( request, _("Successfully censored %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_unicode(opts.verbose_name) else: objects_name = force_unicode(opts.verbose_name_plural) context = { "title": _("Are you sure?"), "object_name": objects_name, "queryset": queryset, "opts": opts, "app_label": app_label, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page return TemplateResponse( request, 'admin/demos/submission/censor_selected_confirmation.html', context, current_app=modeladmin.admin_site.name)
def challenge_selected(modeladmin, request, queryset): """ Default action to challenge selected objects """ ch_count = moderate_selected(modeladmin, request, queryset, CHALLENGED_STATUS) if ch_count: modeladmin.message_user( request, _("Successfully challenged %(count)d %(items)s.") % { "count": ch_count, "items": model_ngettext(modeladmin.opts, ch_count) } ) # Return None to display the change list page again. return None
def approve_selected(modeladmin, request, queryset): """ Default action to approve selected objects """ ap_count = moderate_selected(modeladmin, request, queryset, APPROVED_STATUS) if ap_count: modeladmin.message_user( request, _("Successfully approved %(count)d %(items)s.") % { "count": ap_count, "items": model_ngettext(modeladmin.opts, ap_count) } ) # Return None to display the change list page again. return None
def send_activation_email(self, request, queryset): """ Send activation emails for the selected users, if they are not already activated. """ n = 0 for user in queryset: if not user.is_active and settings.USERS_VERIFY_EMAIL: send_activation_email(user=user, request=request) n += 1 self.message_user( request, _('Activation emails sent to %(count)d %(items)s.') % {'count': n, 'items': model_ngettext(self.opts, n)}, messages.SUCCESS)
def delete_models(self, queryset): n = queryset.count() if n: if self.delete_models_batch: if(self.model_name=='view'): for data in queryset: for field in data._meta.fields: if(field.name=='subjecttype'): s = getattr(data, 'subjecttype') if (s != '-1'): id = getattr(data, 'id') FileExtendInfo.objects.filter(fileId=str(id)).delete() s = getattr(data,field.name) if(os.path.isfile('./media/'+str(s))==True): if(str(s).find("/quanjing/")==-1): os.remove('./media/' + str(s)) else: s = str(s).split("/") str1 = s[0:3] str1 = '/'.join(str1) if(os.path.isdir('./media/'+str1)): shutil.rmtree('./media/'+str1) if(os.path.exists('./media/'+str1+'.zip')): os.remove('./media/'+str1+'.zip') queryset.delete() else: for obj in queryset: if (self.model_name == 'view'): for field in obj._meta.fields: if (field.name == 'subjecttype'): s = getattr(obj, 'subjecttype') if (s != '-1'): id = getattr(obj, 'id') FileExtendInfo.objects.filter(fileId=str(id)).delete() s = getattr(obj, field.name) if (os.path.isfile('./media/' + str(s)) == True): if (str(s).find("/quanjing/") == -1): os.remove('./media/' + str(s)) else: s = str(s).split("/") str1 = s[0:3] str1 = '/'.join(str1) if (os.path.isdir('./media/' + str1)): shutil.rmtree('./media/' + str1) if (os.path.exists('./media/' + str1 + '.zip')): os.remove('./media/' + str1 + '.zip') obj.delete() self.message_user(_("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, 'success')
def activate_users(self, request, queryset): """ Activates the selected users, if they are not already activated. """ n = 0 for user in queryset: if not user.is_active: user.activate() n += 1 self.message_user( request, _('Successfully activated %(count)d %(items)s.') % {'count': n, 'items': model_ngettext(self.opts, n)}, messages.SUCCESS)
def delete_selected(modeladmin, request, queryset): """ Переопределено множественное удаление записи. Добавляем в исключение lock_id_list """ lock_id_list = getattr(modeladmin, 'lock_id_list', []) queryset_without_lock = queryset.exclude(id__in=lock_id_list) count_lock = queryset.filter(id__in=lock_id_list).count() if count_lock: modeladmin.message_user(request, _('%(count)d %(items)s not may be deleted.') % { 'count': count_lock, 'items': model_ngettext(modeladmin.opts, count_lock) }, messages.WARNING) return delete_selected_(modeladmin, request, queryset_without_lock)
def activate_users(self, request, queryset): """ Activates the selected users, if they are not already activated. """ n = 0 for user in queryset: if not user.is_active: user.activate() n += 1 self.message_user( request, _('Successfully activated %(count)d %(items)s.') % { 'count': n, 'items': model_ngettext(self.opts, n) }, messages.SUCCESS)
def send_activation_email(self, request, queryset): """ Send activation emails for the selected users, if they are not already activated. """ n = 0 for user in queryset: if not user.is_active and settings.USERS_VERIFY_EMAIL: send_activation_email(user=user, request=request) n += 1 self.message_user( request, _('Activation emails sent to %(count)d %(items)s.') % { 'count': n, 'items': model_ngettext(self.opts, n) }, messages.SUCCESS)
def recreate_vm(modeladmin, request, queryset): opts = modeladmin.model._meta # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): n = queryset.count() if n: for vm in queryset: from apimws.vm import destroy_vm, recreate_vm try: destroy_vm(vm.id) except: pass recreate_vm(vm.id) modeladmin.message_user( request, "Successfully recreated %(count)d %(items)s." % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.INFO) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) context = dict( modeladmin.admin_site.each_context(request), title="Are you sure?", objects_name=objects_name, list_objects=[queryset], queryset=queryset, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, media=modeladmin.media, ) request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse(request, "admin/recreate_confirmation.html", context)
def test_process_wire(self, process_payment, message_user) -> None: """ Tests that a wire payment is processed correctly """ object_id = "c85ea333-3508-46f1-8cbb-254f8c138020" payment = Payment.objects.create(pk=object_id, amount=7.5) queryset = Payment.objects.filter(pk=object_id) process_payment.return_value = [payment] change_url = reverse("admin:payments_payment_changelist") request_noperms = self.client.post( change_url, { "action": "process_wire_selected", "index": 1, "_selected_action": [object_id], }, ).wsgi_request self._give_user_permissions() request_hasperms = self.client.post( change_url, { "action": "process_wire_selected", "index": 1, "_selected_action": [object_id], }, ).wsgi_request process_payment.reset_mock() message_user.reset_mock() self.admin.process_wire_selected(request_noperms, queryset) process_payment.assert_not_called() self.admin.process_wire_selected(request_hasperms, queryset) process_payment.assert_called_once_with(queryset, self.user, Payment.WIRE) message_user.assert_called_once_with( request_hasperms, _("Successfully processed %(count)d %(items)s.") % { "count": 1, "items": model_ngettext(Payment(), 1) }, messages.SUCCESS, )
def get_csv(modeladmin, request, queryset): """ TODO check OOM on big data """ opts = modeladmin.opts if request.POST.get('post'): field_names = tuple( [field.name for field in opts.fields if field.name not in 'password' or not request.user.is_superuser]) # TODO time format dependency on language time_now = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S') filename = f'{opts}_{time_now}.csv' # Generate streaming response pseudo_buffer = Echo() streaming_writer = csv.writer(pseudo_buffer, delimiter=',') pseudo_buffer.write(field_names) response = StreamingHttpResponse( (streaming_writer.writerow(row) for row in chain([field_names], [ [getattr(obj, field) for field in field_names] for obj in queryset ])), content_type="text/csv") response['Content-Disposition'] = f'attachment; filename={filename}' return response objects_name = model_ngettext(queryset) title = _(f'Get CSV from {objects_name} objects') context = { **modeladmin.admin_site.each_context(request), 'title': title, 'queryset': queryset, 'perms_lacking': [], 'opts': opts, 'objects_name': objects_name, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, } request.current_app = modeladmin.admin_site.name return TemplateResponse( request, "admin/admin_actions/get_csv_confirmation.html", context)
def soft_delete_selected(modeladmin, request, queryset): """ In charge of deactivating instances instead of deleting them """ opts = modeladmin.model._meta using = router.db_for_write(modeladmin.model) count = queryset.count() if not count: return None # soft delete selected items if hasattr(queryset, 'soft_delete'): queryset.soft_delete() else: for obj in queryset: soft_delete_item = getattr(obj, 'soft_delete', None) if not soft_delete_item: modeladmin.message_user( request, _("{verbose_name_plural} has not soft delete available.". format({"verbose_name_plural": opts.verbose_name_plural})), messages.SUCCESS) return None soft_delete_item() # soft delete nested items collector = NestedObjects(using=using) collector.collect(queryset) for model_base, nested_objects_collected in collector.data.items(): if model_base == modeladmin.model or not hasattr( model_base, 'soft_delete'): continue for nested_object in nested_objects_collected: nested_object.soft_delete() # response success message modeladmin.message_user( request, _("Successfully soft deleted {count} {items}.".format( count=count, items=model_ngettext(modeladmin.opts, count))), messages.SUCCESS) return None
def delete_selected(modeladmin, request, queryset): if not modeladmin.has_delete_permission(request): raise PermissionDenied if request.POST.get('post'): count = queryset.count() if count: for object in queryset: modeladmin.log_deletion(request, object, force_text(object)) queryset.delete() modeladmin.message_user( request, _(u'Successfully deleted {count:d} {items:s}.').format( count=count, items=model_ngettext(modeladmin.opts, count), ), messages.SUCCESS, ) return None context = dict( modeladmin.admin_site.each_context(request), action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, objects_name=force_text(modeladmin.model._meta.verbose_name) if len(queryset) == 1 else force_text( modeladmin.model._meta.verbose_name_plural), opts=modeladmin.model._meta, queryset=queryset, title=_('Are you sure?'), ) request.current_app = modeladmin.admin_site.name return TemplateResponse( request, modeladmin.delete_selected_confirmation_template or [ u'admin/{app_label:s}/{model_name:s}/delete_selected_confirmation.html' .format( app_label=modeladmin.model._meta.app_label, model_name=modeladmin.model._meta.model_name, ), u'admin/{app_label:s}/delete_selected_confirmation.html'.format( app_label=modeladmin.model._meta.app_label, ), u'admin/delete_selected_confirmation.html', ], context, )
def delete_selected_groups(self, request, queryset): if self.get_default_queryset(request, queryset).exists(): msg = _('Cannot proceed with the delete operation because ' 'the batch of items contains the default group, ' 'which cannot be deleted') self.message_user(request, msg, messages.ERROR) return False if not self.has_delete_permission(request): raise PermissionDenied n = queryset.count() if n: queryset.delete() self.message_user( request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, messages.SUCCESS) return None
def hard_delete_selected(modeladmin, request, queryset): opts = modeladmin.model._meta # # pylint: disable=W0212 deletable_objects, model_count, perms_needed, protected = modeladmin.get_deleted_objects(queryset, request) if request.POST.get('post') and not protected: if perms_needed: raise PermissionDenied if queryset.count(): number_of_rows_deleted, __ = queryset.hard_delete() # __ = deleted_items if number_of_rows_deleted == 1: message_bit = _('1 record was') else: message_bit = _('%(number_of_rows)s records were') % dict(number_of_rows=number_of_rows_deleted) message = _('%(message_bit)s deleted') % dict(message_bit=message_bit) modeladmin.message_user(request, message) return None objects_name = model_ngettext(queryset) if perms_needed or protected: title = _('Cannot delete %(name)s') % {'name': objects_name} else: title = _('Are you sure?') context = { **modeladmin.admin_site.each_context(request), 'title': title, 'objects_name': str(objects_name), 'deletable_objects': [deletable_objects], 'model_count': dict(model_count).items(), 'queryset': queryset, 'perms_lacking': perms_needed, 'protected': protected, 'opts': opts, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, } request.current_app = modeladmin.admin_site.name return TemplateResponse(request, 'admin/hard_delete_selected_confirmation.html', context)
def test_set_last_used(self, update_last_used, message_user) -> None: """ Tests that the last used value is updated """ update_last_used.return_value = 1 request_noperms = self.rf.post("/", { "action": "set_last_used", "index": 1, "_selected_action": ["bla"] }) request_noperms.user = MagicMock() request_noperms.user.has_perm = lambda _: False request_hasperms = self.rf.post("/", { "action": "set_last_used", "index": 1, "_selected_action": ["bla"] }) request_hasperms.user = MagicMock() request_hasperms.user.has_perm = lambda _: True update_last_used.reset_mock() message_user.reset_mock() queryset_mock = MagicMock() self.admin.set_last_used(request_noperms, queryset_mock) update_last_used.assert_not_called() self.admin.set_last_used(request_hasperms, queryset_mock) update_last_used.assert_called_once_with(queryset_mock) message_user.assert_called_once_with( request_hasperms, _("Successfully updated %(count)d %(items)s.") % { "count": 1, "items": model_ngettext(BankAccount(), 1) }, messages.SUCCESS, )
def get_context_data(self, form, **kw): """Returns additional context for the admin site template""" context = super(TaggitBulkWizard, self).get_context_data(form, **kw) options = self.get_options() data = {} data.update(self.request.session[options['session_prefix']]) content_type = ContentType.objects.get_by_natural_key(data['app_label'], data['model']) model = content_type.model_class() context.update({ 'title': _('Bulk tagging %(number)s %(model_name)s') % { 'model_name': model_ngettext(model._meta, len(data['ids'])), 'number': len(data['ids']) }, 'site_title': admin.site.site_title, 'site_header': admin.site.site_header, 'index_title': admin.site.index_title, 'has_permission': admin.site.has_permission(self.request), 'available_apps': admin.site.get_app_list(self.request), 'is_popup': False, }) return context
def delete_selected(modeladmin, request, queryset): opts = modeladmin.model._meta if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) deletable_objects, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) queryset.delete() modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) return redirect('.')
def test_reject(self, reject_entries): reject_entries.return_value = 1 queryset = [] request = _get_mock_request([]) self.admin.reject_selected(request, queryset) reject_entries.assert_not_called() request = _get_mock_request(["registrations.review_entries"]) self.admin.reject_selected(request, queryset) reject_entries.assert_called_once_with(1, queryset) request._messages.add.assert_called_once_with( messages.SUCCESS, _("Successfully rejected %(count)d %(items)s.") % { "count": 1, "items": model_ngettext(Renewal(), 1) }, "", )
def merge_topics(modeladmin, request, queryset): if request.POST.get("post"): selected = Topic.objects.get(pk=request.POST["selected"]) for obj in queryset: if obj.pk == selected.pk: continue for article in obj.article_set.all(): article.topics.remove(obj) article.topics.add(selected) obj.delete() if count := queryset.count(): modeladmin.message_user( request, _("Successfully merged %(count)d %(items)s.") % { "count": count, "items": model_ngettext(modeladmin.opts, count) }, messages.SUCCESS, ) return None
def change_fields(modeladmin, request, queryset): if request.POST.get('post'): fields = request.POST.get('fields', {}) if fields and isinstance(fields, dict): msg = _(f'Error: Unknown error') try: queryset.update(**fields) msg = _(f'Fields {", ".join(fields.keys())} updated successfully') except (exceptions.FieldDoesNotExist, exceptions.FieldError, exceptions.PermissionDenied, exceptions.TooManyFieldsSent, ValueError, TypeError) as e: msg = _(f'Do not try to hack me.') finally: modeladmin.message_user(request, msg) return None opts = modeladmin.opts objects_name = model_ngettext(queryset) title = _(f'Change multiple fields in {objects_name} objects') context = { **modeladmin.admin_site.each_context(request), 'title': title, 'queryset': queryset, 'perms_lacking': [], 'opts': opts, 'objects_name': objects_name, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, } request.current_app = modeladmin.admin_site.name return TemplateResponse( request, "admin/admin_actions/change_fields_confirmation.html", context)
def anonymize(self, request, queryset): if not request.POST.get('post'): # not confirmed yet; display the confirmation page return TemplateResponse(request,"initadmin/anonymize_users_confirmation.html", { 'opts': self.model._meta, 'users': queryset, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, }) # confirmed; anonymize the users count = queryset.count() if count: for user in queryset: Vote.objects.filter(user=user,initiative__state='v').delete() Avatar.objects.filter(user=user).delete() EmailAddress.objects.filter(user=user).delete() avatar_dir = avatar_storage.path(os.path.join("avatars", str(user.pk))) if os.path.exists(avatar_dir): rmtree(avatar_dir) user.first_name = '' user.last_name = '' user.email = '' user.is_staff = False # for good measure user.is_active = False UserConfig.objects.filter(user=user).delete() for result in user.signupcoderesult_set.all(): result.signup_code.delete() # also deletes the result, by cascading while True: user.username = '******' + str(randint(1, 9999999999)) if not User.objects.filter(username=user.username).exists(): break user.save() self.message_user(request, "%d %s erfolgreich anonymisiert." % (count, model_ngettext(self.opts, count)), messages.SUCCESS) return None
def delete_selected(modeladmin, request, queryset): opts = modeladmin.model._meta if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, model_count, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) remove_program_elasticsearch(program_id=obj.id) queryset.delete() modeladmin.message_user( request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None else: return django_delete_selected(modeladmin, request, queryset)
def delete_selected(modeladmin, request, queryset): """ The out-of-box Django delete never calls Submission.delete(), so this is a mostly redundant lift-and-hack to ensure that happens. This is important because Submission.delete() also cleans up its uploaded files. See also: https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/ """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_unicode(obj) modeladmin.log_deletion(request, obj, obj_display) obj.delete() modeladmin.message_user( request, _("Deleted and uploaded files for %(item)s") % { "item": obj_display }) modeladmin.message_user( request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_unicode(opts.verbose_name) else: objects_name = force_unicode(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { "title": title, "object_name": objects_name, "deletable_objects": [deletable_objects], "queryset": queryset, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": app_label, "action_checkbox_name": helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.object_name.lower()), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context, current_app=modeladmin.admin_site.name)
def groot_view(self, request, object_id): # Only allow superusers to edit permissions if not request.user.is_superuser: raise PermissionDenied model = self.model opts = model._meta obj = self.get_object(request, unquote(object_id)) if obj is None: raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id), }) opts = self.model._meta app_label = opts.app_label group_list = Group.objects.all() group_count = group_list.count() GroupPermissionForm = get_group_permission_form( model_perms=self.get_groot_permissions(request), ) GroupPermissionFormSet = formset_factory( GroupPermissionForm, extra=0, min_num=group_count, validate_min=True, max_num=group_count) obj_group_perms = get_groups_with_perms(obj=obj, attach_perms=True) initial_data = [] for group in group_list: try: group_perms = obj_group_perms[group] except KeyError: group_perms = [] group_initial = { 'group': group, } for perm in group_perms: field_name = '%s%s' % (PERM_PREFIX, perm) group_initial[field_name] = True initial_data.append(group_initial) formset = GroupPermissionFormSet(request.POST or None, initial=initial_data) if formset.is_valid(): # The user has confirmed the update group_count = 0 for form in formset.forms: # Only act on changed data if form.has_changed(): group_count += 1 for field in form.changed_data: group = form.cleaned_data['group'] changed_perm = field.replace(PERM_PREFIX, '', 1) add_perm = form.cleaned_data[field] # Change perm action accordingly if add_perm: update_perm = assign_perm else: update_perm = remove_perm update_perm(perm=changed_perm, user_or_group=group, obj=obj) if group_count: self.message_user(request, _(( 'Successfully updated permissions for %(count)d %(groups)s.' )) % { 'count': group_count, 'groups': model_ngettext(Group, n=group_count), }, messages.SUCCESS) else: self.message_user(request, _('No permissions were updated.'), messages.INFO) return HttpResponseRedirect(request.path) context = self.admin_site.each_context(request) context.update({ 'title': _('Group permissions: %s') % force_text(obj), 'object': obj, 'opts': opts, 'formset': formset, 'group_formsets': zip(group_list, formset.forms), }) request.current_app = self.admin_site.name template_name = getattr(self, 'group_permissions_template', None) or [ 'admin/%s/%s/group_permissions.html' % (app_label, opts.model_name), 'admin/%s/group_permissions.html' % app_label, 'admin/group_permissions.html' ] # Display the form page return TemplateResponse(request, template_name, context)
def undelete_selected(self, request, queryset): """ Admin action to undelete objects in bulk with confirmation. """ if not self.has_delete_permission(request): raise PermissionDenied assert hasattr(queryset, 'undelete') # Remove not deleted item from queryset queryset = queryset.filter(deleted__isnull=False) # Undeletion confirmed if request.POST.get('post'): n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) self.log_undeletion(request, obj, obj_display) queryset.undelete() if django.VERSION[1] <= 4: self.message_user( request, _("Successfully undeleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, ) else: self.message_user( request, _("Successfully undeleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, messages.SUCCESS, ) # Return None to display the change list page again. return None opts = self.model._meta if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) title = _("Are you sure?") context = { 'title': title, 'objects_name': objects_name, 'queryset': queryset, "opts": opts, "app_label": opts.app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } if LooseVersion(django.get_version()) < LooseVersion('1.10'): return TemplateResponse( request, self.undelete_selected_confirmation_template, context, current_app=self.admin_site.name, ) else: return TemplateResponse( request, self.undelete_selected_confirmation_template, context, )
def delete_selected(modeladmin, request, queryset): """ Override default action which deletes the selected objects to handle and display delete exceptions This action first displays a confirmation page whichs shows all the deleteable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, model_count, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: # start: base changes try: queryset.delete() except Exception as e: modeladmin.message_user(request, e.message, messages.ERROR) return None # end: base changes for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) modeladmin.message_user( request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = dict( modeladmin.admin_site.each_context(request), title=title, objects_name=objects_name, deletable_objects=[deletable_objects], model_count=dict(model_count).items(), queryset=queryset, perms_lacking=perms_needed, protected=protected, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, ) request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse( request, modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context)
def _delete_selected(modeladmin, request, queryset): """ Default action which deletes the selected objects. This action first displays a confirmation page whichs shows all the deleteable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it delets all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. # TODO: Permissions would be so cool... deletable_objects, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = len(queryset) if n: for obj in queryset: obj_display = force_unicode(obj) modeladmin.log_deletion(request, obj, obj_display) # call the objects delete method to ensure signals are # processed. obj.delete() # This is what you get if you have to monkey patch every object in a changelist # No queryset object, I can tell ya. So we get a new one and delete that. #pk_list = [o.pk for o in queryset] #klass = queryset[0].__class__ #qs = klass.objects.filter(pk__in=pk_list) #qs.delete() modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_unicode(opts.verbose_name) else: objects_name = force_unicode(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { "title": title, "objects_name": objects_name, "deletable_objects": [deletable_objects], 'queryset': queryset, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "root_path": modeladmin.admin_site.root_path, "app_label": app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page return render_to_response(modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.object_name.lower()), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context, context_instance=template.RequestContext(request))
def soft_delete_selected(modeladmin, request, queryset): """ Replace the default delete_selected action so we can soft delete objects by using obj.delete() instead of queryset.delete(). Default action which deletes the selected objects. This action first displays a confirmation page whichs shows all the deleteable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it soft deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, count, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_unicode(obj) modeladmin.log_deletion(request, obj, obj_display) # Delete the object with it's own method in case the # object has a custom delete method. obj.delete() modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_unicode(opts.verbose_name) else: objects_name = force_unicode(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { "title": title, "objects_name": objects_name, "deletable_objects": [deletable_objects], 'queryset': queryset, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page return TemplateResponse(request, [ "admin/%s/%s/soft_delete_selected_confirmation.html" % (app_label, opts.object_name.lower()), "admin/%s/soft_delete_selected_confirmation.html" % app_label, "admin/soft_delete_selected_confirmation.html" ], context, current_app=modeladmin.admin_site.name)
def delete_selected(modeladmin, request, queryset): """Default ModelAdmin action that deletes the selected objects. Django's default handler doesn't even check the has_delete_permission() of corresponding ModelAdmin with specific instances (only the general permission), and requires django's User model permissions as well. Theese aren't currently used in OIOIOI, so this custom method doesn't care about them. This implementation checks if deleted model is registered in the current AdminSite and if it is, then uses has_delete_permission() with it's instance. It first displays a confirmation page that shows all the deleteable objects, or, if the user has no permission for one of the related objects (foreignkeys), a "permission denied" message. Next, it deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Find related objects and check their permissions # This is a custom method as well to_delete, perms_needed, protected = \ collect_deleted_objects(modeladmin, request, queryset) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) queryset.delete() message_text = _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) } modeladmin.message_user(request, message_text, messages.SUCCESS) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = dict( modeladmin.admin_site.each_context(request), title=title, objects_name=objects_name, deletable_objects=[to_delete], queryset=queryset, perms_lacking=perms_needed, protected=protected, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, ) request.current_app = modeladmin.admin_site.name custom_template = modeladmin.delete_selected_confirmation_template # Display the confirmation page return TemplateResponse(request, custom_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context)
def groot_view(self, request, object_id): # Only allow superusers to edit permissions if not request.user.is_superuser: raise PermissionDenied model = self.model opts = model._meta obj = self.get_object(request, unquote(object_id)) if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': force_text(opts.verbose_name), 'key': escape(object_id), }) opts = self.model._meta app_label = opts.app_label group_list = Group.objects.all() group_count = group_list.count() GroupPermissionForm = get_group_permission_form( model_perms=get_perms_for_model(model)) GroupPermissionFormSet = formset_factory(GroupPermissionForm, extra=0, min_num=group_count, validate_min=True, max_num=group_count) obj_group_perms = get_groups_with_perms(obj=obj, attach_perms=True) initial_data = [] for group in group_list: try: group_perms = obj_group_perms[group] except KeyError: group_perms = [] group_initial = { 'group': group, } for perm in group_perms: field_name = '%s%s' % (PERM_PREFIX, perm) group_initial[field_name] = True initial_data.append(group_initial) formset = GroupPermissionFormSet(request.POST or None, initial=initial_data) if formset.is_valid(): # The user has confirmed the update group_count = 0 for form in formset.forms: # Only act on changed data if form.has_changed(): group_count += 1 for field in form.changed_data: group = form.cleaned_data['group'] changed_perm = field.replace(PERM_PREFIX, '', 1) add_perm = form.cleaned_data[field] # Change perm action accordingly if add_perm: update_perm = assign_perm else: update_perm = remove_perm update_perm(perm=changed_perm, user_or_group=group, obj=obj) if group_count: self.message_user( request, _(('Successfully updated permissions for %(count)d %(groups)s.' )) % { 'count': group_count, 'groups': model_ngettext(Group, n=group_count), }, messages.SUCCESS) else: self.message_user(request, _('No permissions were updated.'), messages.INFO) return HttpResponseRedirect(request.path) if django.VERSION >= (1, 8): context = self.admin_site.each_context(request) else: context = self.admin_site.each_context() context.update({ 'title': _('Group permissions: %s') % force_text(obj), 'object': obj, 'opts': opts, 'formset': formset, 'group_formsets': zip(group_list, formset.forms), }) request.current_app = self.admin_site.name template_name = getattr(self, 'group_permissions_template', None) or [ 'admin/%s/%s/group_permissions.html' % (app_label, opts.model_name), 'admin/%s/group_permissions.html' % app_label, 'admin/group_permissions.html' ] # Display the form page return TemplateResponse(request, template_name, context)
def soft_delete_selected(modeladmin, request, queryset): """ Replace the default delete_selected action so we can soft delete objects by using obj.delete() instead of queryset.delete(). Default action which deletes the selected objects. This action first displays a confirmation page whichs shows all the deleteable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it soft deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, count, perms_needed, protected = get_deleted_objects( queryset, request, modeladmin.admin_site, ) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_str(obj) modeladmin.log_deletion(request, obj, obj_display) # Delete the object with it's own method in case the # object has a custom delete method. obj.delete() modeladmin.message_user( request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_str(opts.verbose_name) else: objects_name = force_str(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { "title": title, "objects_name": objects_name, "deletable_objects": [deletable_objects], 'queryset': queryset, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page request.current_app = modeladmin.admin_site.name return TemplateResponse( request=request, template=[ "admin/%s/%s/soft_delete_selected_confirmation.html" % (app_label, opts.object_name.lower()), "admin/%s/soft_delete_selected_confirmation.html" % app_label, "admin/soft_delete_selected_confirmation.html" ], context=context)
def delete_selected(modeladmin, request, queryset): """ This is a fork of django.contrib.admin.actions.delete_selected But this calls object.delete() instead of queryset.delete() """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) obj.delete() modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { "title": title, "objects_name": objects_name, "deletable_objects": [deletable_objects], 'queryset': queryset, "perms_lacking": perms_needed, "protected": protected, "opts": opts, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context, current_app=modeladmin.admin_site.name)
def merge_selected_tags(modeladmin, request, queryset): """ Default action which deletes the selected objects. This action first displays a confirmation page which shows all the deleteable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model # TOD if not modeladmin.has_delete_permission(request): raise PermissionDenied # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): winner = modeladmin.model.objects.get(pk=request.POST.get('winner')) queryset = queryset.exclude(pk=winner.pk) n = queryset.count() if n: n += 1 # For display we want to include the winner in the count for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) winner.merge(obj) modeladmin.message_user(request, _("Successfully merged %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) title = _("Are you sure?") context = dict( modeladmin.admin_site.each_context(request), title=title, objects_name=objects_name, model_count=queryset.count(), queryset=queryset, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, ) request.current_app = modeladmin.admin_site.name return render(request, "admin/orb/tag/merge_tags_confirmation.html", context)
def delete_related_services(modeladmin, request, queryset): opts = modeladmin.model._meta app_label = opts.app_label using = router.db_for_write(modeladmin.model) collector = NestedObjects(using=using) collector.collect(queryset) registered_services = services.get() related_services = [] to_delete = [] user = request.user admin_site = modeladmin.admin_site def format(obj, account=False): has_admin = obj.__class__ in admin_site._registry opts = obj._meta no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), force_text(obj)) if has_admin: try: admin_url = reverse('admin:%s_%s_change' % (opts.app_label, opts.model_name), None, (quote(obj._get_pk_val()),) ) except NoReverseMatch: # Change url doesn't exist -- don't display link to edit return no_edit_link p = '%s.%s' % (opts.app_label, get_permission_codename('delete', opts)) if not user.has_perm(p): perms_needed.add(opts.verbose_name) # Display a link to the admin page. context = (capfirst(opts.verbose_name), admin_url, obj) if account: context += (_("services to delete:"),) return format_html('{} <a href="{}">{}</a> {}', *context) return format_html('{}: <a href="{}">{}</a>', *context) else: # Don't display link to edit, because it either has no # admin or is edited inline. return no_edit_link def format_nested(objs, result): if isinstance(objs, list): current = [] for obj in objs: format_nested(obj, current) result.append(current) else: result.append(format(objs)) for nested in collector.nested(): if isinstance(nested, list): # Is lists of objects current = [] is_service = False for service in nested: if type(service) in registered_services: if service == main_systemuser: continue current.append(format(service)) to_delete.append(service) is_service = True elif is_service and isinstance(service, list): nested = [] format_nested(service, nested) current.append(nested) is_service = False else: is_service = False related_services.append(current) elif isinstance(nested, modeladmin.model): # Is account # Prevent the deletion of the main system user, which will delete the account main_systemuser = nested.main_systemuser related_services.append(format(nested, account=True)) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): n = queryset.count() if n: for obj in to_delete: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) # TODO This probably will fail in certain conditions, just capture exception obj.delete() modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) context = dict( modeladmin.admin_site.each_context(request), title=_("Are you sure?"), objects_name=objects_name, deletable_objects=[related_services], model_count=dict(collector.model_count).items(), queryset=queryset, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, ) request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context)
def delete_selected(modeladmin, request, queryset): """ This is a fork of django.contrib.admin.actions.delete_selected But this calls object.delete() instead of queryset.delete() """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, perms_needed, protected = get_deleted_objects( queryset, opts, request.user, modeladmin.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) obj.delete() modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { "title": title, "objects_name": objects_name, "deletable_objects": [deletable_objects], 'queryset': queryset, "perms_lacking": perms_needed, "protected": protected, "opts": opts, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context, current_app=modeladmin.admin_site.name)
def delete_selected(modeladmin, request, queryset): """Default ModelAdmin action that deletes the selected objects. Django's default handler doesn't even check the has_delete_permission() of corresponding ModelAdmin with specific instances (only the general permission), and requires django's User model permissions as well. Theese aren't currently used in OIOIOI, so this custom method doesn't care about them. This implementation checks if deleted model is registered in the current AdminSite and if it is, then uses has_delete_permission() with it's instance. It first displays a confirmation page that shows all the deleteable objects, or, if the user has no permission for one of the related objects (foreignkeys), a "permission denied" message. Next, it deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Find related objects and check their permissions # This is a custom method as well to_delete, perms_needed, protected = \ collect_deleted_objects(modeladmin, request, queryset) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) queryset.delete() message_text = _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) } modeladmin.message_user(request, message_text, messages.SUCCESS) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = dict( modeladmin.admin_site.each_context(request), title=title, objects_name=objects_name, deletable_objects=[to_delete], queryset=queryset, perms_lacking=perms_needed, protected=protected, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, ) request.current_app = modeladmin.admin_site.name custom_template = modeladmin.delete_selected_confirmation_template # Display the confirmation page return TemplateResponse(request, custom_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context)
"""
def update_active(modeladmin, request, queryset): """ ENG: Update active for multiple entities RUS: Обновление активных элементов для нескольких объектов """ CHUNK_SIZE = getattr(settings, 'EDW_UPDATE_RELATIONS_ACTION_CHUNK_SIZE', 100) opts = modeladmin.model._meta app_label = opts.app_label if request.POST.get('post'): form = EntitiesUpdateActiveAdminForm(request.POST) if form.is_valid(): to_set_active = form.cleaned_data['to_set_active'] n = queryset.count() if n: i = 0 tasks = [] while i < n: chunk = queryset[i:i + CHUNK_SIZE] for obj in chunk: obj_display = force_text(obj) modeladmin.log_change(request, obj, obj_display) tasks.append(update_entities_active.si([x.id for x in chunk], to_set_active)) i += CHUNK_SIZE chain(reduce(OR, tasks)).apply_async() modeladmin.message_user(request, _("Successfully proceed %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None else: form = EntitiesUpdateActiveAdminForm() if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) title = _("Update active for multiple entities") context = { "title": title, 'form': form, "objects_name": objects_name, 'queryset': queryset, "opts": opts, "app_label": app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, 'action': 'update_active', } # Display the confirmation page kwargs = {} return TemplateResponse(request, "edw/admin/entities/actions/update_active.html", context, **kwargs)
def remove_selected(self, request, queryset): # Populate deletable_objects, a data structure of all related objects that will also be deleted. deletable_objects, model_count, perms_needed, protected = self.get_deleted_objects( queryset, request) # The user has already confirmed the deletion. # Do the deletion and return None to display the change list view again. if request.POST.get('post') and not protected: if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = str(obj) # manually delete the images stored in the cloud if obj.url: try: delete(obj.url) except Exception: continue self.log_deletion(request, obj, obj_display) self.delete_queryset(request, queryset) self.message_user( request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(self.opts, n) }, messages.SUCCESS) # delete all # queryset.delete() # Return None to display the change list page again. return None # intermediate confirmation view else: objects_name = model_ngettext(queryset) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { **self.admin_site.each_context(request), 'title': title, 'queryset': queryset, 'action_checkbox_name': ACTION_CHECKBOX_NAME, 'opts': self.opts, 'objects_name': str(objects_name), 'deletable_objects': [deletable_objects], 'perms_lacking': perms_needed, 'protected': protected, 'model_count': dict(model_count).items(), 'media': self.media, } request.current_app = self.admin_site.name # Display the confirmation page return TemplateResponse( request, 'admin/delete_selected_confirm_images.html', context, )
def update_permissions(modeladmin, request, queryset): opts = modeladmin.model._meta app_label = opts.app_label # Only allow superusers to edit permissions if not request.user.is_superuser: raise PermissionDenied PermissionForm = get_permission_form(modeladmin.model) form = PermissionForm() # The user has confirmed the update if request.POST.get('post'): form = PermissionForm(request.POST) if form.is_valid(): groups = form.cleaned_data['groups'] permissions = form.cleaned_data['permissions'] # Can be either add or remove varying on button if request.POST.get('remove_permissions'): update_perm = remove_perm else: update_perm = assign_perm for obj in queryset: for group in groups: for permission in permissions: update_perm(perm=permission, user_or_group=group, obj=obj) modeladmin.message_user(request, _(( 'Successfully updated permissions for %(group_count)d %(groups)s on ' '%(obj_count)d %(items)s.') ) % { 'group_count': len(groups), 'obj_count': queryset.count(), 'groups': model_ngettext(Group, n=len(groups)), 'items': model_ngettext(queryset), }, messages.SUCCESS) # Display change list page again return None adminForm = helpers.AdminForm( form=form, fieldsets=[(None, {'fields': form.base_fields})], prepopulated_fields={}, model_admin=modeladmin) if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) context = modeladmin.admin_site.each_context(request) context.update({ 'title': _('Update permissions'), 'adminform': adminForm, 'objects_name': objects_name, 'queryset': queryset, 'opts': opts, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, 'form': form, }) request.current_app = modeladmin.admin_site.name template_name = getattr(modeladmin, 'update_permissions_template', None) or [ 'admin/%s/%s/update_permissions.html' % (app_label, opts.model_name), 'admin/%s/update_permissions.html' % app_label, 'admin/update_permissions.html' ] # Display the form page return TemplateResponse(request, template_name, context)
def update_states(modeladmin, request, queryset): """ ENG: Update states for multiple entities RUS: Обновляет состояния для нескольких объектов """ CHUNK_SIZE = getattr(settings, 'EDW_UPDATE_STATES_ACTION_CHUNK_SIZE', 100) opts = modeladmin.model._meta app_label = opts.app_label try: terms_ids = queryset[0].terms.values_list('id', flat=True) except IndexError: entities_model = DataMartModel.get_base_entity_model() else: entities_model = DataMartModel.get_entities_model(terms_ids) if request.POST.get('post'): form = EntitiesUpdateStateAdminForm(request.POST, entities_model=entities_model) if form.is_valid(): state = form.cleaned_data['state'] n = queryset.count() if n and state: i = 0 tasks = [] while i < n: chunk = queryset[i:i + CHUNK_SIZE] for obj in chunk: obj_display = force_text(obj) modeladmin.log_change(request, obj, obj_display) tasks.append(update_entities_states.si([x.id for x in chunk], state)) i += CHUNK_SIZE chain(reduce(OR, tasks)).apply_async() modeladmin.message_user(request, _("Successfully proceed %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None else: form = EntitiesUpdateStateAdminForm(entities_model=entities_model) if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) title = _("Update state for multiple entities") context = { "title": title, 'form': form, "objects_name": objects_name, 'queryset': queryset, "opts": opts, "app_label": app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, 'action': 'update_states', } # Display the confirmation page kwargs = {} return TemplateResponse(request, "edw/admin/entities/actions/update_states.html", context, **kwargs)
def copy_selected(modeladmin, request, queryset): """ Action which copies the selected objects. This action first displays a confirmation page which shows all the creatable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it copies all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Populate creatable_objects, a data structure of all related objects that # will also be created. creatable_objects, model_count, perms_needed, collector = get_copied_objects( queryset, request, modeladmin.admin_site, handlers=getattr(modeladmin, 'copy_selected_handlers', None) ) # The user has already confirmed the deletion. # Do the creation and return None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: change_message = modeladmin.construct_change_message( request, None, None, True) modeladmin.log_addition(request, obj, change_message) # copy all objects with related objects collector.copy() modeladmin.message_user( request, _("Successfully created %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None objects_name = model_ngettext(queryset) if perms_needed: title = _("Cannot create %(name)s") % {"name": objects_name,} else: title = _("Are you sure?") context = { **modeladmin.admin_site.each_context(request), 'title': title, 'objects_name': str(objects_name), 'creatable_objects': [creatable_objects], 'model_count': dict(model_count).items(), 'queryset': queryset, 'perms_lacking': perms_needed, 'opts': opts, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, } request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse( request, getattr(modeladmin, 'copy_selected_confirmation_template', None) or [ "admin/%s/%s/copy_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/copy_selected_confirmation.html" % app_label, "admin/copy_selected_confirmation.html" ], context )
def unpublish_selected(modeladmin, request, queryset): queryset = queryset.select_for_update() opts = modeladmin.model._meta app_label = opts.app_label all_unpublished = [] for obj in queryset: obj_public = obj.unpublish(dry_run=True) if obj_public: all_unpublished.append(obj_public) perms_needed = [] _check_permissions(modeladmin, all_unpublished, request, perms_needed) using = router.db_for_write(modeladmin.model) # Populate unpublishable_objects, a data structure of all related objects that # will also be deleted. unpublishable_objects, _perms_needed, protected = get_deleted_objects( all_unpublished, opts, request.user, modeladmin.admin_site, using) if request.POST.get('post'): if perms_needed: raise PermissionDenied n = len(all_unpublished) if n: for obj in queryset: obj_public = obj.unpublish() if obj_public: modeladmin.log_publication(request, object, message="Unpublished") modeladmin.message_user( request, _("Successfully unpublished %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None if len(all_unpublished) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot unpublish %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { "title": title, "objects_name": objects_name, "unpublishable_objects": [unpublishable_objects], 'queryset': queryset, "perms_lacking": perms_needed, "protected": protected, "opts": opts, "app_label": app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, } # Display the confirmation page return TemplateResponse( request, modeladmin.unpublish_confirmation_template or [ "admin/%s/%s/unpublish_selected_confirmation.html" % (app_label, opts.object_name.lower()), "admin/%s/unpublish_selected_confirmation.html" % app_label, "admin/unpublish_selected_confirmation.html" ], context, current_app=modeladmin.admin_site.name)
def update_additional_characteristics_or_marks(modeladmin, request, queryset): """ ENG: Update additional marks for multiple entities RUS: Обновление дополнительных характеристик или меток для нескольких объектов """ CHUNK_SIZE = getattr( settings, 'EDW_UPDATE_ADDITIONAL_CHARACTERISTICS_OR_MARKS_ACTION_CHUNK_SIZE', 100) opts = modeladmin.model._meta app_label = opts.app_label if request.POST.get('post'): form = EntitiesUpdateAdditionalCharacteristicsOrMarksAdminForm( request.POST) if form.is_valid(): to_set_term = form.cleaned_data['to_set_term'] to_unset_term = form.cleaned_data['to_unset_term'] value = form.cleaned_data['value'] view_class = form.cleaned_data['view_class'] n = queryset.count() if n and (to_set_term and value or to_unset_term): i = 0 tasks = [] while i < n: chunk = queryset[i:i + CHUNK_SIZE] for obj in chunk: obj_display = force_text(obj) modeladmin.log_change(request, obj, obj_display) tasks.append( update_entities_additional_characteristics_or_marks.si( [x.id for x in chunk], to_set_term.id if to_set_term else None, value, view_class, to_unset_term.id if to_unset_term else None)) i += CHUNK_SIZE chain(reduce(OR, tasks)).apply_async() modeladmin.message_user( request, _("Successfully proceed %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }) # Return None to display the change list page again. return None else: form = EntitiesUpdateAdditionalCharacteristicsOrMarksAdminForm() if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) title = _( "Update additional characteristics or marks for multiple entities") context = { "title": title, 'form': form, "objects_name": objects_name, 'queryset': queryset, "opts": opts, "app_label": app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, 'action': 'update_additional_characteristics_or_marks', } # Display the confirmation page kwargs = {} return TemplateResponse( request, "edw/admin/entities/actions/update_additional_characteristics_or_marks.html", context, **kwargs)
def delete_related_objects(modeladmin, request, queryset): """ Action that deletes related objects for the selected items. This action first displays a confirmation page whichs shows all the deleteable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it deletes all related objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) first_level_related_objects = [] collector = NestedObjects(using=using) collector.collect(queryset) for base_object_or_related_list in collector.nested(): if type(base_object_or_related_list) is not list: # If it's not a list, it's a base object. Skip it. continue for obj in base_object_or_related_list: if type(obj) is list: # A list here contains related objects for the previous # element. We can skip it since delete() on the first # level of related objects will cascade. continue elif not isinstance(obj, _ReadOnlyModel): first_level_related_objects.append(obj) # Populate deletable_objects, a data structure of (string representations # of) all related objects that will also be deleted. deletable_objects, model_count, perms_needed, protected = get_deleted_objects( first_level_related_objects, opts, request.user, modeladmin.admin_site, using ) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = 0 with transaction.atomic(using): for obj in first_level_related_objects: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) obj.delete() n += 1 modeladmin.message_user( request, _("Successfully deleted %(count)d related objects.") % { "count": n, "items": model_ngettext(modeladmin.opts, n)}, messages.SUCCESS ) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = dict( modeladmin.admin_site.each_context(request), title=title, objects_name=objects_name, deletable_objects=[deletable_objects], model_count=dict(model_count).items(), queryset=queryset, perms_lacking=perms_needed, protected=protected, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, ) request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse( request, "delete_related_for_selected_confirmation.html", context, current_app=modeladmin.admin_site.name)
def delete_related_objects(modeladmin, request, queryset): """ Action that deletes related objects for the selected items. This action first displays a confirmation page whichs shows all the deleteable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it deletes all related objects and redirects back to the change list. The code is mostly copied from django/contrib/admin/actions.py """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) first_level_related_objects = [] collector = NestedObjects(using=using) collector.collect(queryset) for base_object_or_related_list in collector.nested(): if type(base_object_or_related_list) is not list: # If it's not a list, it's a base object. Skip it. continue for obj in base_object_or_related_list: if type(obj) is list: # A list here contains related objects for the previous # element. We can skip it since delete() on the first # level of related objects will cascade. continue elif not isinstance(obj, _ShadowModel): first_level_related_objects.append(obj) # Populate deletable_objects, a data structure of (string representations # of) all related objects that will also be deleted. deletable_objects, model_count, perms_needed, protected = get_deleted_objects( first_level_related_objects, opts, request.user, modeladmin.admin_site, using ) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if request.POST.get('post'): if perms_needed: raise PermissionDenied n = 0 with transaction.atomic(using): for obj in first_level_related_objects: obj_display = force_text(obj) modeladmin.log_deletion(request, obj, obj_display) obj.delete() n += 1 modeladmin.message_user( request, _("Successfully deleted %(count)d related objects.") % { "count": n, "items": model_ngettext(modeladmin.opts, n)}, messages.SUCCESS ) # Return None to display the change list page again. return None if len(queryset) == 1: objects_name = force_text(opts.verbose_name) else: objects_name = force_text(opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = dict( modeladmin.admin_site.each_context(request), title=title, objects_name=objects_name, deletable_objects=[deletable_objects], model_count=dict(model_count).items(), queryset=queryset, perms_lacking=perms_needed, protected=protected, opts=opts, action_checkbox_name=helpers.ACTION_CHECKBOX_NAME, ) request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse( request, "delete_related_for_selected_confirmation.html", context, current_app=modeladmin.admin_site.name)
def delete_selected(modeladmin, request, queryset): """ Default action which deletes the selected objects. This action first displays a confirmation page which shows all the deletable objects, or, if the user.txt has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, model_count, perms_needed, protected = modeladmin.get_deleted_objects( queryset, request) # The user.txt has already confirmed the deletion. # Do the deletion and return None to display the change list view again. if request.POST.get('post') and not protected: if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = str(obj) modeladmin.log_deletion(request, obj, obj_display) modeladmin.delete_queryset(request, queryset) modeladmin.message_user( request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None objects_name = model_ngettext(queryset) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { **modeladmin.admin_site.each_context(request), 'title': title, 'objects_name': str(objects_name), 'deletable_objects': [deletable_objects], 'model_count': dict(model_count).items(), 'queryset': queryset, 'perms_lacking': perms_needed, 'protected': protected, 'opts': opts, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, } request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse( request, modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context)
def delete_selected(modeladmin, request, queryset): """ Default action which deletes the selected objects. This action first displays a confirmation page which shows all the deletable objects, or, if the user has no permission one of the related childs (foreignkeys), a "permission denied" message. Next, it deletes all selected objects and redirects back to the change list. """ opts = modeladmin.model._meta app_label = opts.app_label # Check that the user has delete permission for the actual model if not modeladmin.has_delete_permission(request): raise PermissionDenied using = router.db_for_write(modeladmin.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, model_count, perms_needed, protected = get_deleted_objects( queryset, request.user, modeladmin.admin_site, using, ) # The user has already confirmed the deletion. # Do the deletion and return None to display the change list view again. if request.POST.get('post') and not protected: if perms_needed: raise PermissionDenied n = queryset.count() if n: for obj in queryset: obj_display = str(obj) modeladmin.log_deletion(request, obj, obj_display) modeladmin.delete_queryset(request, queryset) modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % { "count": n, "items": model_ngettext(modeladmin.opts, n) }, messages.SUCCESS) # Return None to display the change list page again. return None objects_name = model_ngettext(queryset) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = { **modeladmin.admin_site.each_context(request), 'title': title, 'objects_name': str(objects_name), 'deletable_objects': [deletable_objects], 'model_count': dict(model_count).items(), 'queryset': queryset, 'perms_lacking': perms_needed, 'protected': protected, 'opts': opts, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'media': modeladmin.media, } request.current_app = modeladmin.admin_site.name # Display the confirmation page return TemplateResponse(request, modeladmin.delete_selected_confirmation_template or [ "admin/%s/%s/delete_selected_confirmation.html" % (app_label, opts.model_name), "admin/%s/delete_selected_confirmation.html" % app_label, "admin/delete_selected_confirmation.html" ], context)
def undelete_selected(self, request, queryset): """ Admin action to undelete objects in bulk with confirmation. """ original_queryset = queryset.all() if not self.has_delete_permission(request): raise PermissionDenied assert hasattr(queryset, 'undelete') # Remove not deleted item from queryset queryset = queryset.filter(**{FIELD_NAME + '__isnull': False}) # Undeletion confirmed if request.POST.get('post'): requested = queryset.count() if requested: for obj in queryset: obj_display = force_str(obj) self.log_undeletion(request, obj, obj_display) queryset.undelete() changed = original_queryset.filter(**{FIELD_NAME + '__isnull': True}).count() if changed < requested: self.message_user( request, _("Successfully undeleted %(count_changed)d of the " "%(count_requested)d selected %(items)s.") % { "count_requested": requested, "count_changed": changed, "items": model_ngettext(self.opts, requested) }, messages.WARNING, ) else: self.message_user( request, _("Successfully undeleted %(count)d %(items)s.") % { "count": requested, "items": model_ngettext(self.opts, requested) }, messages.SUCCESS, ) # Return None to display the change list page again. return None opts = self.model._meta if len(queryset) == 1: objects_name = force_str(opts.verbose_name) else: objects_name = force_str(opts.verbose_name_plural) title = _("Are you sure?") related_list = [list(related_objects(obj)) for obj in queryset] context = { 'title': title, 'objects_name': objects_name, 'queryset': queryset, "opts": opts, "app_label": opts.app_label, 'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME, 'related_list': related_list } if parse_version(django.get_version()) < parse_version('1.10'): return TemplateResponse( request, self.undelete_selected_confirmation_template, context, current_app=self.admin_site.name, ) else: return TemplateResponse( request, self.undelete_selected_confirmation_template, context, )
def deactivate_objects(self, request, queryset): """Admin action to set is_active=False on objects""" count = queryset.update(is_active=False) self.message_user(request, _("Successfully deactivated %(count)d %(items)s.") % { "count": count, "items": model_ngettext(self.opts, count) })