page.copy to use `exclude_fields_in_copy` child & parental m2m relations

- fixes #5099
- test_copy_page_with_excluded_parental_and_child_relations
- ensure the tests are wrapped in a try/finally so that the model is always reset back even if tests fail
- update page model tests
pull/5969/head
LB Johnston 2019-03-17 17:05:57 +10:00 zatwierdzone przez LB
rodzic a69559174f
commit ce815a5f00
4 zmienionych plików z 70 dodań i 0 usunięć

Wyświetl plik

@ -44,6 +44,7 @@ Changelog
* 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)
* Fix: `exclude_fields_in_copy` on Page models will now work for for modelcluster parental / many to many relations (LB (Ben Johnston))
2.8.1 (14.04.2020)

Wyświetl plik

@ -62,6 +62,7 @@ Bug fixes
* 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)
* ``exclude_fields_in_copy`` on Page models will now work for for modelcluster parental / many to many relations (LB (Ben Johnston))
Upgrade considerations

Wyświetl plik

@ -1136,6 +1136,10 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
# copy child m2m relations
for related_field in get_all_child_m2m_relations(specific_self):
# Ignore explicitly excluded fields
if related_field.name in exclude_fields:
continue
field = getattr(specific_self, related_field.name)
if field and hasattr(field, 'all'):
values = field.all()
@ -1180,6 +1184,9 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
parental_key_name = child_relation.field.attname
child_objects = getattr(specific_self, accessor_name, None)
# Ignore explicitly excluded fields
if accessor_name in exclude_fields:
continue
if child_objects:
for child_object in child_objects.all():

Wyświetl plik

@ -1195,6 +1195,67 @@ class TestCopyPage(TestCase):
# special_field is in the list to be excluded
self.assertNotEqual(page.special_field, new_page.special_field)
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."""
try:
# modify excluded fields for this test
EventPage.exclude_fields_in_copy = ['advert_placements', 'categories', 'signup_link']
# set up data
christmas_event = EventPage.objects.get(url_path='/home/events/christmas/')
summer_category = EventCategory.objects.create(name='Summer')
holiday_category = EventCategory.objects.create(name='Holidays')
# add URL (to test excluding a basic field)
christmas_event.signup_link = "https://christmas-is-awesome.com/rsvp"
# add parental many to many relations
christmas_event.categories = (summer_category, holiday_category)
christmas_event.save()
# Copy it
new_christmas_event = christmas_event.copy(
update_attrs={'title': "New christmas event", 'slug': 'new-christmas-event'}
)
# check that the signup_link was NOT copied
self.assertEqual(christmas_event.signup_link, "https://christmas-is-awesome.com/rsvp")
self.assertEqual(new_christmas_event.signup_link, '')
# check that original event is untouched
self.assertEqual(
christmas_event.categories.count(),
2,
"Child objects (parental many to many) defined on the superclass were removed from the original page"
)
# check that parental many to many are NOT copied
self.assertEqual(
new_christmas_event.categories.count(),
0,
"Child objects (parental many to many) were copied but should be excluded"
)
# check that child objects on original event were left untouched
self.assertEqual(
christmas_event.advert_placements.count(),
1,
"Child objects defined on the original superclass were edited when copied"
)
# check that child objects were NOT copied
self.assertEqual(
new_christmas_event.advert_placements.count(),
0,
"Child objects defined on the superclass were copied and should not be"
)
finally:
# reset excluded fields for future tests
EventPage.exclude_fields_in_copy = []
class TestSubpageTypeBusinessRules(TestCase, WagtailTestUtils):
def test_allowed_subpage_models(self):