From 555adccc2a6ff22db63f5d943a2ded48688936cf Mon Sep 17 00:00:00 2001 From: Nick Smith Date: Tue, 7 Apr 2020 10:20:23 +0100 Subject: [PATCH] Set TreeQueryset.delete.queryset_only = True (#5938) Fixes wagtail/wagtail#5937 This reverts Wagtail's behaviour to match Django's, where an error is raised as a safety mechanism. Projects relying on the non-safe behaviour should update e.g. `MyModel.objects.delete()` to `MyModel.objects.all().delete()`. --- CHANGELOG.txt | 1 + docs/releases/2.9.rst | 7 +++++++ wagtail/core/query.py | 6 ++++++ wagtail/core/tests/test_page_queryset.py | 8 ++++++++ 4 files changed, 22 insertions(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2cf3affa0a..3c579e11fc 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -43,6 +43,7 @@ Changelog * Fix: Hide empty 'view live' links (Karran Besen) * Fix: Mark up a few strings for translation (Luiz Boaretto) * Fix: Invalid focal_point attribute on image edit view (Michał (Quadric) Sieradzki) + * Fix: No longer expose the `.delete()` method on the default Page.objects manager (Nick Smith) 2.8.1 (14.04.2020) diff --git a/docs/releases/2.9.rst b/docs/releases/2.9.rst index 7701a5504a..32d8404eb4 100644 --- a/docs/releases/2.9.rst +++ b/docs/releases/2.9.rst @@ -61,6 +61,7 @@ Bug fixes * Hide empty 'view live' links (Karran Besen) * Mark up a few strings for translation (Luiz Boaretto) * Invalid focal_point attribute on image edit view (Michał (Quadric) Sieradzki) + * No longer expose the ``.delete()`` method on the default Page.objects manager (Nick Smith) Upgrade considerations @@ -76,3 +77,9 @@ Django 2.1 is no longer supported as of this release; please upgrade to Django 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Wagtail's :class:`~wagtail.core.middleware.SiteMiddleware`, which makes the current site object available as the property ``request.site``, is now deprecated as it clashes with Django's sites framework and makes unnecessary database queries on non-Wagtail views. References to ``request.site`` in your code should be removed; the recommended way of retrieving the current site is ``Site.find_for_request(request)`` in Python code, and the ``{% wagtail_site %}`` tag within Django templates. Once these are removed, ``'wagtail.core.middleware.SiteMiddleware'`` can be removed from your project's ``MIDDLEWARE`` setting. + + +Page / Collection managers no longer expose a ``delete`` method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For `consistency with standard Django models `_, the ``delete()`` method is no longer available on the default Page and Collection managers. Code such as ``Page.objects.delete()`` should be changed to ``Page.objects.all().delete()``. diff --git a/wagtail/core/query.py b/wagtail/core/query.py index 20bea63ea5..fa38cba009 100644 --- a/wagtail/core/query.py +++ b/wagtail/core/query.py @@ -15,6 +15,12 @@ class TreeQuerySet(MP_NodeQuerySet): """ Extends Treebeard's MP_NodeQuerySet with additional useful tree-related operations. """ + def delete(self): + """Redefine the delete method unbound, so we can set the queryset_only parameter. """ + super().delete() + + delete.queryset_only = True + def descendant_of_q(self, other, inclusive=False): q = Q(path__startswith=other.path) & Q(depth__gte=other.depth) diff --git a/wagtail/core/tests/test_page_queryset.py b/wagtail/core/tests/test_page_queryset.py index 7c03d94309..820170a970 100644 --- a/wagtail/core/tests/test_page_queryset.py +++ b/wagtail/core/tests/test_page_queryset.py @@ -406,6 +406,14 @@ class TestPageQuerySet(TestCase): self.assertTrue(Page.objects.filter(query).exists()) + def test_delete_queryset(self): + Page.objects.all().delete() + self.assertEqual(Page.objects.count(), 0) + + def test_delete_is_not_available_on_manager(self): + with self.assertRaises(AttributeError): + Page.objects.delete() + class TestPageQueryInSite(TestCase): fixtures = ['test.json']