Ignore GenericRelation in page copy

Co-Authored-By: John-Scott Atlakson <john-scott@greenlightgo.co>
stable/2.15.x
Dan Braghis 2022-04-10 09:38:35 +01:00
rodzic 2559d57c13
commit 0b6bd865e9
6 zmienionych plików z 75 dodań i 3 usunięć

Wyświetl plik

@ -7,6 +7,7 @@ Changelog
* Fix: Allow bulk publishing of pages without revisions (Andy Chosak)
* Fix: Ensure that all descendant pages are logged when deleting a page, not just immediate children (Jake Howard)
* Fix: Translation key `IntegrityError` when publishing pages with translatable `Orderable`s that were copied without being published (Kalob Taulien, Dan Braghis)
* Fix: Ignore `GenericRelation` when copying pages (John-Scott Atlakson)
2.15.4 (11.02.2022)

Wyświetl plik

@ -16,6 +16,7 @@ Bug fixes
* Allow bulk publishing of pages without revisions (Andy Chosak)
* Ensure that all descendant pages are logged when deleting a page, not just immediate children (Jake Howard)
* Generate new translation keys for translatable ``Orderable`` when page is copied without being published (Kalob Taulien, Dan Braghis)
* Ignore `GenericRelation` when copying pages (John-Scott Atlakson)
Upgrade considerations

Wyświetl plik

@ -1,3 +1,4 @@
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from modelcluster.models import ClusterableModel
@ -21,6 +22,10 @@ def _extract_field_data(source, exclude_fields=None):
if field.auto_created:
continue
# Ignore reverse generic relations
if isinstance(field, GenericRelation):
continue
# Copy parental m2m relations
if field.many_to_many:
if isinstance(field, ParentalManyToManyField):

Wyświetl plik

@ -27,8 +27,9 @@ from wagtail.tests.testapp.models import (
BusinessIndex, BusinessNowherePage, BusinessSubIndex, CustomManager, CustomManagerPage,
CustomPageQuerySet, EventCategory, EventIndex, EventPage, EventPageSpeaker, GenericSnippetPage,
ManyToManyBlogPage, MTIBasePage, MTIChildPage, MyCustomPage, OneToOnePage,
PageWithExcludedCopyField, SimpleChildPage, SimplePage, SimpleParentPage, SingleEventPage,
SingletonPage, StandardIndex, StreamPage, TaggedGrandchildPage, TaggedPage)
PageWithExcludedCopyField, PageWithGenericRelation, RelatedGenericRelation, SimpleChildPage,
SimplePage, SimpleParentPage, SingleEventPage, SingletonPage, StandardIndex, StreamPage,
TaggedGrandchildPage, TaggedPage)
from wagtail.tests.utils import WagtailTestUtils
@ -1630,6 +1631,26 @@ class TestCopyPage(TestCase):
# special_field is in the list to be excluded
self.assertNotEqual(page.special_field, new_page.special_field)
def test_page_with_generic_relation(self):
"""Test that a page with a GenericRelation will have that relation ignored when
copying.
"""
homepage = Page.objects.get(url_path="/home/")
original_page = homepage.add_child(
instance=PageWithGenericRelation(
title="PageWithGenericRelation",
slug="page-with-generic-relation",
live=True,
has_unpublished_changes=False,
)
)
RelatedGenericRelation.objects.create(content_object=original_page)
self.assertIsNotNone(original_page.generic_relation.first())
page_copy = original_page.copy(
to=homepage, update_attrs={"slug": f"{original_page.slug}-2"}
)
self.assertIsNone(page_copy.generic_relation.first())
def test_copy_page_with_excluded_parental_and_child_relations(self):
"""Test that a page will be copied with parental and child relations removed if excluded."""

Wyświetl plik

@ -0,0 +1,34 @@
# Generated by Django 3.2.12 on 2022-04-10 08:36
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0066_collection_management_permissions'),
('contenttypes', '0002_remove_content_type_name'),
('tests', '0060_taggedchildpage_taggedgrandchildpage'),
]
operations = [
migrations.CreateModel(
name='PageWithGenericRelation',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='RelatedGenericRelation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')),
],
),
]

Wyświetl plik

@ -5,7 +5,7 @@ import uuid
from django import forms
from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
@ -169,6 +169,16 @@ class PageWithExcludedCopyField(Page):
]
class RelatedGenericRelation(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
class PageWithGenericRelation(Page):
generic_relation = GenericRelation("tests.RelatedGenericRelation")
class PageWithOldStyleRouteMethod(Page):
"""
Prior to Wagtail 0.4, the route() method on Page returned an HttpResponse