Fixed #15522 -- Added ModelAdmin.delete_queryset() to customize "delete selected objects" deletion.
This commit is contained in:
parent
ec2ce4517a
commit
777f216d55
|
@ -45,7 +45,7 @@ def delete_selected(modeladmin, request, queryset):
|
||||||
for obj in queryset:
|
for obj in queryset:
|
||||||
obj_display = str(obj)
|
obj_display = str(obj)
|
||||||
modeladmin.log_deletion(request, obj, obj_display)
|
modeladmin.log_deletion(request, obj, obj_display)
|
||||||
queryset.delete()
|
modeladmin.delete_queryset(request, queryset)
|
||||||
modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
|
modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
|
||||||
"count": n, "items": model_ngettext(modeladmin.opts, n)
|
"count": n, "items": model_ngettext(modeladmin.opts, n)
|
||||||
}, messages.SUCCESS)
|
}, messages.SUCCESS)
|
||||||
|
|
|
@ -1043,6 +1043,10 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
"""
|
"""
|
||||||
obj.delete()
|
obj.delete()
|
||||||
|
|
||||||
|
def delete_queryset(self, request, queryset):
|
||||||
|
"""Given a queryset, delete it from the database."""
|
||||||
|
queryset.delete()
|
||||||
|
|
||||||
def save_formset(self, request, form, formset, change):
|
def save_formset(self, request, form, formset, change):
|
||||||
"""
|
"""
|
||||||
Given an inline formset save it to the database.
|
Given an inline formset save it to the database.
|
||||||
|
|
|
@ -27,8 +27,9 @@ models. For example, here's the user module from Django's built-in
|
||||||
has an important caveat: your model's ``delete()`` method will not be
|
has an important caveat: your model's ``delete()`` method will not be
|
||||||
called.
|
called.
|
||||||
|
|
||||||
If you wish to override this behavior, simply write a custom action which
|
If you wish to override this behavior, you can override
|
||||||
accomplishes deletion in your preferred manner -- for example, by calling
|
:meth:`.ModelAdmin.delete_queryset` or write a custom action which does
|
||||||
|
deletion in your preferred manner -- for example, by calling
|
||||||
``Model.delete()`` for each of the selected items.
|
``Model.delete()`` for each of the selected items.
|
||||||
|
|
||||||
For more background on bulk deletion, see the documentation on :ref:`object
|
For more background on bulk deletion, see the documentation on :ref:`object
|
||||||
|
|
|
@ -1391,6 +1391,15 @@ templates used by the :class:`ModelAdmin` views:
|
||||||
operations. Call ``super().delete_model()`` to delete the object using
|
operations. Call ``super().delete_model()`` to delete the object using
|
||||||
:meth:`.Model.delete`.
|
:meth:`.Model.delete`.
|
||||||
|
|
||||||
|
.. method:: ModelAdmin.delete_queryset(request, queryset)
|
||||||
|
|
||||||
|
.. versionadded:: 2.1
|
||||||
|
|
||||||
|
The ``delete_queryset()`` method is given the ``HttpRequest`` and a
|
||||||
|
``QuerySet`` of objects to be deleted. Override this method to customize
|
||||||
|
the deletion process for the "delete selected objects" :doc:`action
|
||||||
|
<actions>`.
|
||||||
|
|
||||||
.. method:: ModelAdmin.save_formset(request, form, formset, change)
|
.. method:: ModelAdmin.save_formset(request, form, formset, change)
|
||||||
|
|
||||||
The ``save_formset`` method is given the ``HttpRequest``, the parent
|
The ``save_formset`` method is given the ``HttpRequest``, the parent
|
||||||
|
|
|
@ -37,6 +37,9 @@ Minor features
|
||||||
|
|
||||||
* jQuery is upgraded from version 2.2.3 to 3.2.1.
|
* jQuery is upgraded from version 2.2.3 to 3.2.1.
|
||||||
|
|
||||||
|
* The new :meth:`.ModelAdmin.delete_queryset` method allows customizing the
|
||||||
|
deletion process of the "delete selected objects" action.
|
||||||
|
|
||||||
:mod:`django.contrib.admindocs`
|
:mod:`django.contrib.admindocs`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -232,6 +232,10 @@ class SubscriberAdmin(admin.ModelAdmin):
|
||||||
actions = ['mail_admin']
|
actions = ['mail_admin']
|
||||||
action_form = MediaActionForm
|
action_form = MediaActionForm
|
||||||
|
|
||||||
|
def delete_queryset(self, request, queryset):
|
||||||
|
SubscriberAdmin.overridden = True
|
||||||
|
super().delete_queryset(request, queryset)
|
||||||
|
|
||||||
def mail_admin(self, request, selected):
|
def mail_admin(self, request, selected):
|
||||||
EmailMessage(
|
EmailMessage(
|
||||||
'Greetings from a ModelAdmin action',
|
'Greetings from a ModelAdmin action',
|
||||||
|
|
|
@ -9,6 +9,7 @@ from django.template.response import TemplateResponse
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from .admin import SubscriberAdmin
|
||||||
from .forms import MediaActionForm
|
from .forms import MediaActionForm
|
||||||
from .models import (
|
from .models import (
|
||||||
Actor, Answer, ExternalSubscriber, Question, Subscriber,
|
Actor, Answer, ExternalSubscriber, Question, Subscriber,
|
||||||
|
@ -128,6 +129,19 @@ class AdminActionsTest(TestCase):
|
||||||
# The page doesn't display a link to the nonexistent change page.
|
# The page doesn't display a link to the nonexistent change page.
|
||||||
self.assertContains(response, '<li>Unchangeable object: %s</li>' % obj, 1, html=True)
|
self.assertContains(response, '<li>Unchangeable object: %s</li>' % obj, 1, html=True)
|
||||||
|
|
||||||
|
def test_delete_queryset_hook(self):
|
||||||
|
delete_confirmation_data = {
|
||||||
|
ACTION_CHECKBOX_NAME: [self.s1.pk, self.s2.pk],
|
||||||
|
'action': 'delete_selected',
|
||||||
|
'post': 'yes',
|
||||||
|
'index': 0,
|
||||||
|
}
|
||||||
|
SubscriberAdmin.overridden = False
|
||||||
|
self.client.post(reverse('admin:admin_views_subscriber_changelist'), delete_confirmation_data)
|
||||||
|
# SubscriberAdmin.delete_queryset() sets overridden to True.
|
||||||
|
self.assertIs(SubscriberAdmin.overridden, True)
|
||||||
|
self.assertEqual(Subscriber.objects.all().count(), 0)
|
||||||
|
|
||||||
def test_custom_function_mail_action(self):
|
def test_custom_function_mail_action(self):
|
||||||
"""A custom action may be defined in a function."""
|
"""A custom action may be defined in a function."""
|
||||||
action_data = {
|
action_data = {
|
||||||
|
|
Loading…
Reference in New Issue