From 55ff37e0fa722533ce002b6309529bd5211d8feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sun, 6 Mar 2016 16:00:53 +0100 Subject: [PATCH] general: fix site import when link cells refer to future cells (#8598) --- combo/data/models.py | 30 ++++++++++++++++++++++-------- tests/test_pages.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/combo/data/models.py b/combo/data/models.py index 7f6f638..0ff4d8a 100644 --- a/combo/data/models.py +++ b/combo/data/models.py @@ -65,7 +65,15 @@ def element_is_visible(element, user=None): return len(set(page_groups).intersection(user.groups.all())) > 0 +class PageManager(models.Manager): + def get_by_natural_key(self, path): + parts = [x for x in path.strip('/').split('/') if x] or ['index'] + return self.get(slug=parts[-1]) + + class Page(models.Model): + objects = PageManager() + title = models.CharField(_('Title'), max_length=50) slug = models.SlugField(_('Slug')) template_name = models.CharField(_('Template'), max_length=50) @@ -86,6 +94,9 @@ class Page(models.Model): def __unicode__(self): return self.title + def natural_key(self): + return (self.get_online_url().strip('/'), ) + def save(self, *args, **kwargs): if not self.order: max_order = Page.objects.all().aggregate(Max('order')).get('order__max') or 0 @@ -182,13 +193,11 @@ class Page(models.Model): def get_serialized_page(self): cells = CellBase.get_cells(page_id=self.id) - serialized_page = json.loads(serializers.serialize('json', [self]))[0] - del serialized_page['pk'] + serialized_page = json.loads(serializers.serialize('json', [self], + use_natural_foreign_keys=True, use_natural_primary_keys=True))[0] del serialized_page['model'] - del serialized_page['fields']['parent'] - if self.parent_id: - serialized_page['parent_slug'] = self.parent.slug - serialized_page['cells'] = json.loads(serializers.serialize('json', cells)) + serialized_page['cells'] = json.loads(serializers.serialize('json', + cells, use_natural_foreign_keys=True, use_natural_primary_keys=True)) for cell in serialized_page['cells']: del cell['pk'] del cell['fields']['page'] @@ -202,20 +211,25 @@ class Page(models.Model): page = [x for x in serializers.deserialize('json', json.dumps([json_page]))][0] page.save() for cell in json_page.get('cells'): - cell['fields']['page'] = page.object.id + cell['fields']['page'] = page.object.natural_key() # if there were cells, remove them for cell in CellBase.get_cells(page_id=page.object.id): cell.delete() + @classmethod + def load_serialized_cells(cls, cells): # load new cells - for cell in serializers.deserialize('json', json.dumps(json_page.get('cells'))): + for cell in serializers.deserialize('json', json.dumps(cells)): cell.save() @classmethod def load_serialized_pages(cls, json_site): + cells = [] for json_page in json_site: cls.load_serialized_page(json_page) + cells.extend(json_page.get('cells')) + cls.load_serialized_cells(cells) # 2nd pass to set parents for json_page in json_site: diff --git a/tests/test_pages.py b/tests/test_pages.py index 79aadcc..1e55973 100644 --- a/tests/test_pages.py +++ b/tests/test_pages.py @@ -1,7 +1,7 @@ import pytest from django.contrib.auth.models import User, Group -from combo.data.models import Page +from combo.data.models import Page, CellBase, TextCell, LinkCell pytestmark = pytest.mark.django_db @@ -112,3 +112,52 @@ def test_page_visibility(): assert not page.is_visible() assert page.is_visible(user1) assert not page.is_visible(user2) + +def test_import_export_pages(): + page = Page(title='foo', slug='foo', order=0) + page.save() + + cell = TextCell(page=page, text='foo', order=0) + cell.save() + + page2 = Page(title='bar', slug='bar', order=1, parent=page) + page2.save() + + cell = TextCell(page=page2, text='bar', order=0) + cell.save() + + site_export = [x.get_serialized_page() for x in Page.objects.all()] + Page.objects.all().delete() + + Page.load_serialized_pages(site_export) + + new_page_1 = Page.objects.all().order_by('order')[0] + new_page_2 = Page.objects.all().order_by('order')[1] + assert new_page_1.title == 'foo' + assert new_page_2.title == 'bar' + assert len(CellBase.get_cells(page_id=new_page_1.id)) == 1 + assert isinstance(CellBase.get_cells(page_id=new_page_1.id)[0], TextCell) + assert CellBase.get_cells(page_id=new_page_1.id)[0].text == 'foo' + +def test_import_export_pages_with_links(): + page = Page(title='foo', slug='foo', order=0) + page.save() + + page2 = Page(title='bar', slug='bar', order=1) + page2.save() + + cell = LinkCell(page=page, title='bar', link_page=page2, order=1) + cell.save() + + cell2 = LinkCell(page=page2, title='foo', link_page=page, order=1) + cell2.save() + + site_export = [x.get_serialized_page() for x in Page.objects.all()] + Page.objects.all().delete() + + Page.load_serialized_pages(site_export) + + new_page_1 = Page.objects.all().order_by('order')[0] + new_page_2 = Page.objects.all().order_by('order')[1] + assert CellBase.get_cells(page_id=new_page_1.id)[0].link_page_id == new_page_2.id + assert CellBase.get_cells(page_id=new_page_2.id)[0].link_page_id == new_page_1.id -- 2.7.0