7

Ensure variants are deleted for page decendants

This commit is contained in:
Alastair Weakley
2018-11-22 09:03:37 +11:00
parent 1e69d929aa
commit d775ef57e6
2 changed files with 36 additions and 7 deletions

View File

@ -4,6 +4,7 @@ import logging
from django.conf.urls import include, url from django.conf.urls import include, url
from django.db import transaction from django.db import transaction
from django.db.models import F
from django.http import Http404 from django.http import Http404
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.template.defaultfilters import pluralize from django.template.defaultfilters import pluralize
@ -19,6 +20,7 @@ from wagtail.core.models import Page
from wagtail_personalisation import admin_urls, models, utils from wagtail_personalisation import admin_urls, models, utils
from wagtail_personalisation.adapters import get_segment_adapter from wagtail_personalisation.adapters import get_segment_adapter
from wagtail_personalisation.models import PersonalisablePageMetadata
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -276,14 +278,22 @@ def delete_related_variants(request, page):
if request.method == 'POST': if request.method == 'POST':
parent_id = page.get_parent().id parent_id = page.get_parent().id
variants_metadata = variants_metadata.select_related('variant')
with transaction.atomic(): with transaction.atomic():
for metadata in variants_metadata.iterator(): # To ensure variants are deleted for all descendants, start with
# Call delete() on objects to trigger any signals or hooks. # the deepest ones, and explicitly delete variants and metadata
metadata.variant.delete() # for all of them, including the page itself. Otherwise protected
# Delete the page's main variant and the page itself. # foreign key constraints are violated. Only consider canonical
page.personalisation_metadata.delete() # pages.
page.delete() for metadata in PersonalisablePageMetadata.objects.filter(
canonical_page__in=page.get_descendants(inclusive=True),
variant=F("canonical_page"),
).order_by('-canonical_page__depth'):
for variant_metadata in metadata.variants_metadata.select_related('variant'):
# Call delete() on objects to trigger any signals or hooks.
variant_metadata.variant.delete()
metadata.delete()
metadata.canonical_page.delete()
msg = _("Page '{0}' and its variants deleted.") msg = _("Page '{0}' and its variants deleted.")
messages.success( messages.success(
request, request,

View File

@ -4,6 +4,7 @@ from django.http import Http404
from wagtail.core.models import Page from wagtail.core.models import Page
from tests.factories.page import ContentPageFactory
from tests.factories.segment import SegmentFactory from tests.factories.segment import SegmentFactory
from wagtail_personalisation import adapters, wagtail_hooks from wagtail_personalisation import adapters, wagtail_hooks
@ -124,3 +125,21 @@ def test_custom_delete_page_view_deletes_variants(rf, segmented_page, user):
# Make sure all the variant pages have been deleted. # Make sure all the variant pages have been deleted.
assert not len(variants.all()) assert not len(variants.all())
assert not len(variants_metadata.all()) assert not len(variants_metadata.all())
@pytest.mark.django_db
def test_custom_delete_page_view_deletes_variants_of_child_pages(rf, segmented_page, user):
"""
Regression test for deleting pages that have children with variants
"""
post_request = rf.post('/')
user.is_superuser = True
rf.user = user
canonical_page = segmented_page.personalisation_metadata.canonical_page
# Create a child with a variant
child_page = ContentPageFactory(parent=canonical_page, slug='personalised-child')
child_page.personalisation_metadata.copy_for_segment(segmented_page.personalisation_metadata.segment)
# A ProtectedError would be raised if the bug persists
wagtail_hooks.delete_related_variants(
post_request, canonical_page
)