|
1 | 1 | import json
|
2 | 2 | import logging
|
| 3 | +from collections.abc import Iterable |
3 | 4 |
|
4 | 5 | import reversion
|
5 | 6 | from django import forms
|
6 | 7 | from django.conf import settings
|
7 | 8 | from django.contrib import admin, messages
|
8 | 9 | from django.contrib.admin import helpers
|
| 10 | +from django.contrib.admin.actions import delete_selected |
9 | 11 | from django.contrib.admin.models import ADDITION, LogEntry
|
10 | 12 | from django.contrib.contenttypes.models import ContentType
|
11 | 13 | from django.core.exceptions import (
|
@@ -566,8 +568,6 @@ def has_delete_permission(self, request, obj=None):
|
566 | 568 | perm = super().has_delete_permission(request)
|
567 | 569 | if not obj:
|
568 | 570 | return perm
|
569 |
| - if obj._has_config(): |
570 |
| - perm = perm and obj.config.is_deactivated() |
571 | 571 | return perm and obj.is_deactivated()
|
572 | 572 |
|
573 | 573 | def save_form(self, request, form, change):
|
@@ -765,22 +765,42 @@ def deactivate_device(self, request, queryset):
|
765 | 765 | def activate_device(self, request, queryset):
|
766 | 766 | self._change_device_status(request, queryset, 'activate')
|
767 | 767 |
|
768 |
| - def get_deleted_objects(self, objs, request, *args, **kwargs): |
769 |
| - # Ensure that all selected devices can be deleted, i.e. |
770 |
| - # the device should be flagged as deactivated and if it has |
771 |
| - # a config object, it's status should be "deactivated". |
772 |
| - active_devices = [] |
773 |
| - for obj in objs: |
774 |
| - if not self.has_delete_permission(request, obj): |
775 |
| - active_devices.append(obj) |
776 |
| - if active_devices: |
777 |
| - return ( |
778 |
| - active_devices, |
779 |
| - {self.model._meta.verbose_name_plural: len(active_devices)}, |
780 |
| - ['active_devices'], |
781 |
| - [], |
| 768 | + @admin.action(description=delete_selected.short_description, permissions=['delete']) |
| 769 | + def delete_selected(self, request, queryset): |
| 770 | + response = delete_selected(self, request, queryset) |
| 771 | + if not response: |
| 772 | + return response |
| 773 | + if 'active_devices' in response.context_data.get('perms_lacking', {}): |
| 774 | + active_devices = [] |
| 775 | + for device in queryset.iterator(): |
| 776 | + if not device.is_deactivated() or ( |
| 777 | + device._has_config() and not device.config.is_deactivated() |
| 778 | + ): |
| 779 | + active_devices.append(self._get_device_path(device)) |
| 780 | + response.context_data.update( |
| 781 | + { |
| 782 | + 'active_devices': active_devices, |
| 783 | + 'perms_lacking': set(), |
| 784 | + 'title': _('Are you sure?'), |
| 785 | + } |
782 | 786 | )
|
783 |
| - return super().get_deleted_objects(objs, request, *args, **kwargs) |
| 787 | + return response |
| 788 | + |
| 789 | + def get_deleted_objects(self, objs, request, *args, **kwargs): |
| 790 | + to_delete, model_count, perms_needed, protected = super().get_deleted_objects( |
| 791 | + objs, request, *args, **kwargs |
| 792 | + ) |
| 793 | + if ( |
| 794 | + isinstance(perms_needed, Iterable) |
| 795 | + and len(perms_needed) == 1 |
| 796 | + and list(perms_needed)[0] == self.model._meta.verbose_name |
| 797 | + and objs.filter(_is_deactivated=False).exists() |
| 798 | + ): |
| 799 | + if request.POST.get("post"): |
| 800 | + perms_needed = set() |
| 801 | + else: |
| 802 | + perms_needed = {'active_devices'} |
| 803 | + return to_delete, model_count, perms_needed, protected |
784 | 804 |
|
785 | 805 | def get_fields(self, request, obj=None):
|
786 | 806 | """
|
@@ -900,6 +920,17 @@ def recover_view(self, request, version_id, extra_context=None):
|
900 | 920 | request._recover_view = True
|
901 | 921 | return super().recover_view(request, version_id, extra_context)
|
902 | 922 |
|
| 923 | + def delete_view(self, request, object_id, extra_context=None): |
| 924 | + extra_context = extra_context or {} |
| 925 | + obj = self.get_object(request, object_id) |
| 926 | + if obj and obj._has_config() and not obj.config.is_deactivated(): |
| 927 | + extra_context['deactivating_warning'] = True |
| 928 | + return super().delete_view(request, object_id, extra_context) |
| 929 | + |
| 930 | + def delete_model(self, request, obj): |
| 931 | + force_delete = request.POST.get('force_delete') == 'true' |
| 932 | + obj.delete(check_deactivated=not force_delete) |
| 933 | + |
903 | 934 | def get_inlines(self, request, obj):
|
904 | 935 | inlines = super().get_inlines(request, obj)
|
905 | 936 | # this only makes sense in existing devices
|
|
0 commit comments