From cf068ec94abb8d67eb5276b3730e93bb82fa39c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Wed, 21 Sep 2022 16:49:05 +0200 Subject: [PATCH] manager: reduce num of queries on page view (#69400) --- combo/apps/wcs/models.py | 23 ++++++++++++++++------- combo/data/models.py | 17 ++++++++++++++--- combo/manager/forms.py | 2 ++ combo/manager/views.py | 7 ++++++- combo/settings.py | 2 +- tests/test_manager.py | 4 ++-- tests/wcs/test_card.py | 4 ++-- 7 files changed, 43 insertions(+), 16 deletions(-) diff --git a/combo/apps/wcs/models.py b/combo/apps/wcs/models.py index 89831e8c..ff425ba3 100644 --- a/combo/apps/wcs/models.py +++ b/combo/apps/wcs/models.py @@ -33,6 +33,7 @@ from django.utils.translation import gettext_lazy as _ from django.utils.translation import pgettext_lazy from requests.exceptions import RequestException +from combo import utils from combo.data.library import register_cell_class from combo.data.models import CellBase, Page from combo.utils import NothingInCacheException, requests @@ -1144,13 +1145,8 @@ class WcsCardCell(CardMixin, CellBase): # get cells with explicit ids results = [] - cells = ( - WcsCardCell.objects.filter(page=self.page_id) - .exclude(pk=self.pk) - .exclude(slug='') # no slug - .filter(related_card_path='') # no explicit ids - .exclude(card_ids__contains=',') # multiple ids, can not follow relations - ) + cells = WcsCardCell.get_cells_with_explicit_ids_by_page().get(self.page_id) or [] + cells = [c for c in cells if c.pk != self.pk] many_cells = len(cells) > 1 for cell in cells: # follow relations @@ -1165,6 +1161,19 @@ class WcsCardCell(CardMixin, CellBase): ) return results + @classmethod + @utils.cache_during_request + def get_cells_with_explicit_ids_by_page(cls): + result = collections.defaultdict(list) + cells = ( + cls.objects.exclude(slug='') # no slug + .filter(related_card_path='') # no explicit ids + .exclude(card_ids__contains=',') # multiple ids, can not follow relations + ).order_by('order') + for cell in cells: + result[cell.page_id].append(cell) + return result + def get_card_ids_from_related(self, context, request): def get_relation(relations, varname, reverse): for relation in relations: diff --git a/combo/data/models.py b/combo/data/models.py index 37a95e20..a6608439 100644 --- a/combo/data/models.py +++ b/combo/data/models.py @@ -928,14 +928,21 @@ class CellBase(models.Model, metaclass=CellMeta): def cleaned_extra_css_class(self): return ' '.join([x for x in self.extra_css_class.split() if not x.startswith('size--')]) - @property - def asset_css_classes(self): + @classmethod + @utils.cache_during_request + def get_assets_by_key(cls): from combo.apps.assets.models import Asset + return {a.key: a for a in Asset.objects.all()} + + @property + def asset_css_classes(self): if not hasattr(self, '_asset_keys'): self._asset_keys = self.get_asset_slot_keys() if not hasattr(self, '_assets'): - self._assets = {a.key: a for a in Asset.objects.filter(key__in=self._asset_keys.keys())} + all_assets = CellBase.get_assets_by_key() + self._assets = {key: all_assets.get(key) for key in self._asset_keys.keys()} + self._assets = {k: v for k, v in self._assets.items() if v} if not self._asset_keys or not self._assets: return '' @@ -1024,6 +1031,7 @@ class CellBase(models.Model, metaclass=CellMeta): cell_filter=None, skip_cell_cache=False, prefetch_validity_info=False, + prefetch_groups=False, select_related=None, load_contenttypes=False, cells_exclude=None, @@ -1066,6 +1074,8 @@ class CellBase(models.Model, metaclass=CellMeta): cells_queryset = cells_queryset.exclude(cells_exclude) if extra_filter: cells_queryset = cells_queryset.filter(extra_filter) + if prefetch_groups: + cells_queryset = cells_queryset.prefetch_related('groups') if select_related: cells_queryset = cells_queryset.select_related( *select_related.get('__all__', []), *select_related.get(klass.get_cell_type_str(), []) @@ -1079,6 +1089,7 @@ class CellBase(models.Model, metaclass=CellMeta): for v in validity_info_list if v.object_id == cell.pk and v.content_type.model_class() == cell.__class__ ] + cells.sort(key=lambda x: x.order) return cells diff --git a/combo/manager/forms.py b/combo/manager/forms.py index c6375cc8..0d2de775 100644 --- a/combo/manager/forms.py +++ b/combo/manager/forms.py @@ -25,12 +25,14 @@ from django.template import Template, TemplateSyntaxError from django.template.loader import TemplateDoesNotExist, get_template from django.utils.translation import gettext_lazy as _ +from combo import utils from combo.data.forms import get_page_choices from combo.data.models import Page, ParentContentCell, SiteSettings, compile_sub_slug from .fields import ImageIncludingSvgField +@utils.cache_during_request def get_groups_as_choices(): return [(x.id, x.name) for x in Group.objects.all().order_by('name')] diff --git a/combo/manager/views.py b/combo/manager/views.py index 1a146f5d..14003071 100644 --- a/combo/manager/views.py +++ b/combo/manager/views.py @@ -419,7 +419,12 @@ class PageView(ManagedPageMixin, DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - cells = CellBase.get_cells(page=self.object, prefetch_validity_info=True) + cells = CellBase.get_cells( + page=self.object, + prefetch_validity_info=True, + prefetch_groups=True, + select_related={'__all__': ['page']}, + ) existing_cell_types = {cell.get_cell_type_str() for cell in cells} cell_type_groups = {} for cell_type in CellBase.get_all_cell_types(): diff --git a/combo/settings.py b/combo/settings.py index 9a4ec5ad..b123728e 100644 --- a/combo/settings.py +++ b/combo/settings.py @@ -274,7 +274,7 @@ LINGO_NO_ONLINE_PAYMENT_REASONS = {} JSON_CELL_TYPES = {} # dashboard support -COMBO_DASHBOARD_ENABLED = True +COMBO_DASHBOARD_ENABLED = False COMBO_DASHBOARD_NEW_TILE_POSITION = 'last' diff --git a/tests/test_manager.py b/tests/test_manager.py index 736afd2c..2e86b8d1 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -702,7 +702,7 @@ def test_edit_page_num_queries(settings, app, admin_user): app.get('/manage/pages/%s/' % page.pk) # load once to populate caches with CaptureQueriesContext(connection) as ctx: app.get('/manage/pages/%s/' % page.pk) - assert len(ctx.captured_queries) == 44 + assert len(ctx.captured_queries) == 40 def test_delete_page(app, admin_user): @@ -2557,7 +2557,7 @@ def test_page_versionning(app, admin_user): resp = resp.click('restore', index=6) with CaptureQueriesContext(connection) as ctx: resp = resp.form.submit().follow() - assert len(ctx.captured_queries) == 153 + assert len(ctx.captured_queries) == 147 resp2 = resp.click('See online') assert resp2.text.index('Foobar1') < resp2.text.index('Foobar2') < resp2.text.index('Foobar3') diff --git a/tests/wcs/test_card.py b/tests/wcs/test_card.py index 49ab0431..b6201cfd 100644 --- a/tests/wcs/test_card.py +++ b/tests/wcs/test_card.py @@ -686,23 +686,23 @@ def test_manager_card_cell(mock_send, app, admin_user): assert resp.forms[0]['c%s-related_card_path' % cell.get_reference()].options == [ ('__all__', False, 'All cards'), ('--', True, 'Card whose identifier is in the URL'), + ('sluge-bis/cardd-bar/carde-foo', False, 'Linked card (From cell sluge-bis): "Card D" -> "Card E"'), ( 'sluge-again/cardd-bar/carde-foo', False, 'Linked card (From cell sluge-again): "Card D" -> "Card E"', ), - ('sluge-bis/cardd-bar/carde-foo', False, 'Linked card (From cell sluge-bis): "Card D" -> "Card E"'), ('', False, 'Template'), ] assert resp.forms[1]['c%s-related_card_path' % cell2.get_reference()].options == [ ('__all__', False, 'All cards'), ('--', True, 'Card whose identifier is in the URL'), + ('sluge/cardd-bar/carde-foo', False, 'Linked card (From cell sluge): "Card D" -> "Card E"'), ( 'sluge-again/cardd-bar/carde-foo', False, 'Linked card (From cell sluge-again): "Card D" -> "Card E"', ), - ('sluge/cardd-bar/carde-foo', False, 'Linked card (From cell sluge): "Card D" -> "Card E"'), ('', False, 'Template'), ]