general: create page hierarchy beforehand (#24238)
This commit is contained in:
parent
9e6adee4f9
commit
35d9a1bbba
|
@ -95,8 +95,8 @@ def get_page_dict(request, page, manifest):
|
|||
if page_dict.get('external') and icon_cells[0].embed_page:
|
||||
page_dict['external'] = False
|
||||
|
||||
if hasattr(page, '_children') and page._children:
|
||||
children = page._children
|
||||
if page.slug == 'index' and page.parent_id is None: # home
|
||||
children = page.get_siblings()[1:]
|
||||
else:
|
||||
children = page.get_children()
|
||||
|
||||
|
@ -143,18 +143,11 @@ def generate_manifest(request):
|
|||
# - the application pages are created from the homepage siblings and their
|
||||
# children
|
||||
# - the application menu is created from direct children of the homepage
|
||||
children = []
|
||||
homepage = None
|
||||
for page in level0_pages:
|
||||
if page.slug == 'index':
|
||||
homepage = page
|
||||
else:
|
||||
children.append(page)
|
||||
|
||||
if not homepage:
|
||||
try:
|
||||
homepage = Page.objects.get(slug='index', parent_id=None)
|
||||
except Page.DoesNotExist:
|
||||
raise GenerationError(_('The homepage needs to be created first.'))
|
||||
|
||||
homepage._children = children
|
||||
manifest.update(get_page_dict(request, homepage, manifest))
|
||||
|
||||
# footer
|
||||
|
|
|
@ -145,7 +145,6 @@ class Page(models.Model):
|
|||
related_cells = JSONField(blank=True)
|
||||
|
||||
_level = None
|
||||
_children = None
|
||||
|
||||
class Meta:
|
||||
ordering = ['order']
|
||||
|
@ -185,7 +184,7 @@ class Page(models.Model):
|
|||
pages = [self]
|
||||
page = self
|
||||
while page.parent_id:
|
||||
page = page.parent
|
||||
page = page._parent if hasattr(page, '_parent') else page.parent
|
||||
pages.append(page)
|
||||
return list(reversed(pages))
|
||||
|
||||
|
@ -202,7 +201,7 @@ class Page(models.Model):
|
|||
parts = [self]
|
||||
page = self
|
||||
while page.parent_id:
|
||||
page = page.parent
|
||||
page = page._parent if hasattr(page, '_parent') else page.parent
|
||||
parts.append(page)
|
||||
parts.reverse()
|
||||
try:
|
||||
|
@ -211,12 +210,19 @@ class Page(models.Model):
|
|||
return None
|
||||
|
||||
def get_siblings(self):
|
||||
return Page.objects.filter(parent=self.parent)
|
||||
if hasattr(self, '_parent'):
|
||||
if self._parent:
|
||||
return self._parent._children
|
||||
return Page.objects.filter(parent_id=self.parent_id)
|
||||
|
||||
def get_children(self):
|
||||
if hasattr(self, '_children'):
|
||||
return self._children
|
||||
return Page.objects.filter(parent_id=self.id)
|
||||
|
||||
def has_children(self):
|
||||
if hasattr(self, '_children'):
|
||||
return bool(self._children)
|
||||
return Page.objects.filter(parent_id=self.id).exists()
|
||||
|
||||
def get_template_display_name(self):
|
||||
|
@ -282,7 +288,6 @@ class Page(models.Model):
|
|||
parenting[page.parent_id].append(page)
|
||||
def fill_list(object_sublist, level=0, parent=None):
|
||||
for page in object_sublist:
|
||||
page._children = parenting.get(page.id)
|
||||
if page.parent == parent:
|
||||
page.level = level
|
||||
reordered.append(page)
|
||||
|
@ -291,6 +296,23 @@ class Page(models.Model):
|
|||
fill_list(object_list)
|
||||
return reordered
|
||||
|
||||
@staticmethod
|
||||
@utils.cache_during_request
|
||||
def get_with_hierarchy_attributes():
|
||||
pages = Page.objects.all()
|
||||
pages_by_id = {}
|
||||
for page in pages:
|
||||
pages_by_id[page.id] = page
|
||||
page._parent = None
|
||||
page._children = []
|
||||
for page in pages:
|
||||
page._parent = pages_by_id[page.parent_id] if page.parent_id else None
|
||||
if page._parent:
|
||||
page._parent._children.append(page)
|
||||
for page in pages:
|
||||
page._children.sort(key=lambda x: x.order)
|
||||
return pages_by_id
|
||||
|
||||
def visibility(self):
|
||||
if self.public:
|
||||
return _('Public')
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
from django.template.loader import get_template
|
||||
|
||||
from combo.data.models import Page
|
||||
|
||||
|
||||
def render_menu(context, level=0, root_page=None, depth=1):
|
||||
context['root_page'] = root_page
|
||||
if root_page:
|
||||
|
@ -25,17 +28,23 @@ def render_menu(context, level=0, root_page=None, depth=1):
|
|||
return template.render(context)
|
||||
|
||||
def get_menu_context(context, level=0, current_page=None, depth=1):
|
||||
if 'hierarchical_pages_by_id' not in context:
|
||||
context['hierarchical_pages_by_id'] = Page.get_with_hierarchy_attributes()
|
||||
pages_by_id = context['hierarchical_pages_by_id']
|
||||
context['depth'] = depth
|
||||
if current_page is None:
|
||||
current_page = context['page']
|
||||
current_page = pages_by_id.get(context['page'].id, context['page'])
|
||||
else:
|
||||
current_page = pages_by_id.get(current_page.id, current_page)
|
||||
|
||||
if 'root_page' in context:
|
||||
root_page = pages_by_id[context['root_page'].id] if context.get('root_page') else None
|
||||
# if the menu is anchored at a specific root page, we make sure the
|
||||
# current page is in the right path, otherwise we fall back to using
|
||||
# the root page as base.
|
||||
ariane = current_page.get_parents_and_self()
|
||||
if not context.get('root_page') in ariane:
|
||||
page_of_level = context['root_page']
|
||||
if not root_page in ariane:
|
||||
page_of_level = root_page
|
||||
else:
|
||||
page_of_level = current_page.get_page_of_level(level)
|
||||
else:
|
||||
|
@ -51,7 +60,7 @@ def get_menu_context(context, level=0, current_page=None, depth=1):
|
|||
context['menuitems'] = []
|
||||
return context
|
||||
else:
|
||||
if page_of_level is context.get('root_page'):
|
||||
if page_of_level == context.get('root_page'):
|
||||
elements = page_of_level.get_children()
|
||||
else:
|
||||
elements = page_of_level.get_siblings()
|
||||
|
|
|
@ -103,20 +103,21 @@ def test_page_footer_acquisition(app):
|
|||
page5.save()
|
||||
ParentContentCell(page=page5, placeholder='footer', order=0).save()
|
||||
|
||||
# check growth in SQL queries is limited to an additional page lookup
|
||||
# check growth in SQL queries is limited
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = app.get('/second/third/', status=200)
|
||||
assert resp.body.count('BARFOO') == 1
|
||||
assert resp.body.count('BAR2FOO') == 1
|
||||
queries_count_third = len(ctx.captured_queries)
|
||||
assert queries_count_third == queries_count_second + 1
|
||||
assert queries_count_third == queries_count_second
|
||||
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = app.get('/second/third/fourth/', status=200)
|
||||
assert resp.body.count('BARFOO') == 1
|
||||
assert resp.body.count('BAR2FOO') == 1
|
||||
queries_count_fourth = len(ctx.captured_queries)
|
||||
assert queries_count_fourth == queries_count_second + 2
|
||||
# +1 for get_parents_and_self()
|
||||
assert queries_count_fourth == queries_count_second + 1
|
||||
|
||||
# check footer doesn't get duplicated in real index children
|
||||
page6 = Page(title='Sixth', slug='sixth', template_name='standard', parent=page_index)
|
||||
|
|
Loading…
Reference in New Issue