0001-manager-reduce-num-of-queries-on-page-view-69400.patch
combo/apps/wcs/models.py | ||
---|---|---|
33 | 33 |
from django.utils.translation import pgettext_lazy |
34 | 34 |
from requests.exceptions import RequestException |
35 | 35 | |
36 |
from combo import utils |
|
36 | 37 |
from combo.data.library import register_cell_class |
37 | 38 |
from combo.data.models import CellBase, Page |
38 | 39 |
from combo.utils import NothingInCacheException, requests |
... | ... | |
1143 | 1144 | |
1144 | 1145 |
# get cells with explicit ids |
1145 | 1146 |
results = [] |
1146 |
cells = ( |
|
1147 |
WcsCardCell.objects.filter(page=self.page_id) |
|
1148 |
.exclude(pk=self.pk) |
|
1149 |
.exclude(slug='') # no slug |
|
1150 |
.filter(related_card_path='') # no explicit ids |
|
1151 |
.exclude(card_ids__contains=',') # multiple ids, can not follow relations |
|
1152 |
) |
|
1147 |
cells = WcsCardCell.get_cells_with_explicit_ids_by_page().get(self.page_id) or [] |
|
1148 |
cells = [c for c in cells if c.pk != self.pk] |
|
1153 | 1149 |
many_cells = len(cells) > 1 |
1154 | 1150 |
for cell in cells: |
1155 | 1151 |
# follow relations |
... | ... | |
1164 | 1160 |
) |
1165 | 1161 |
return results |
1166 | 1162 | |
1163 |
@classmethod |
|
1164 |
@utils.cache_during_request |
|
1165 |
def get_cells_with_explicit_ids_by_page(cls): |
|
1166 |
result = collections.defaultdict(list) |
|
1167 |
cells = ( |
|
1168 |
cls.objects.exclude(slug='') # no slug |
|
1169 |
.filter(related_card_path='') # no explicit ids |
|
1170 |
.exclude(card_ids__contains=',') # multiple ids, can not follow relations |
|
1171 |
).order_by('order') |
|
1172 |
for cell in cells: |
|
1173 |
result[cell.page_id].append(cell) |
|
1174 |
return result |
|
1175 | ||
1167 | 1176 |
def get_card_ids_from_related(self, context, request): |
1168 | 1177 |
def get_relation(relations, varname, reverse): |
1169 | 1178 |
for relation in relations: |
combo/data/models.py | ||
---|---|---|
927 | 927 |
def cleaned_extra_css_class(self): |
928 | 928 |
return ' '.join([x for x in self.extra_css_class.split() if not x.startswith('size--')]) |
929 | 929 | |
930 |
@property |
|
931 |
def asset_css_classes(self): |
|
930 |
@classmethod |
|
931 |
@utils.cache_during_request |
|
932 |
def get_assets_by_key(cls): |
|
932 | 933 |
from combo.apps.assets.models import Asset |
933 | 934 | |
935 |
return {a.key: a for a in Asset.objects.all()} |
|
936 | ||
937 |
@property |
|
938 |
def asset_css_classes(self): |
|
934 | 939 |
if not hasattr(self, '_asset_keys'): |
935 | 940 |
self._asset_keys = self.get_asset_slot_keys() |
936 | 941 |
if not hasattr(self, '_assets'): |
937 |
self._assets = {a.key: a for a in Asset.objects.filter(key__in=self._asset_keys.keys())} |
|
942 |
all_assets = CellBase.get_assets_by_key() |
|
943 |
self._assets = {key: all_assets.get(key) for key in self._asset_keys.keys()} |
|
944 |
self._assets = {k: v for k, v in self._assets.items() if v} |
|
938 | 945 | |
939 | 946 |
if not self._asset_keys or not self._assets: |
940 | 947 |
return '' |
... | ... | |
1023 | 1030 |
cell_filter=None, |
1024 | 1031 |
skip_cell_cache=False, |
1025 | 1032 |
prefetch_validity_info=False, |
1033 |
prefetch_groups=False, |
|
1026 | 1034 |
select_related=None, |
1027 | 1035 |
load_contenttypes=False, |
1028 | 1036 |
cells_exclude=None, |
... | ... | |
1065 | 1073 |
cells_queryset = cells_queryset.exclude(cells_exclude) |
1066 | 1074 |
if extra_filter: |
1067 | 1075 |
cells_queryset = cells_queryset.filter(extra_filter) |
1076 |
if prefetch_groups: |
|
1077 |
cells_queryset = cells_queryset.prefetch_related('groups') |
|
1068 | 1078 |
if select_related: |
1069 | 1079 |
cells_queryset = cells_queryset.select_related( |
1070 | 1080 |
*select_related.get('__all__', []), *select_related.get(klass.get_cell_type_str(), []) |
... | ... | |
1078 | 1088 |
for v in validity_info_list |
1079 | 1089 |
if v.object_id == cell.pk and v.content_type.model_class() == cell.__class__ |
1080 | 1090 |
] |
1091 | ||
1081 | 1092 |
cells.sort(key=lambda x: x.order) |
1082 | 1093 |
return cells |
1083 | 1094 |
combo/manager/forms.py | ||
---|---|---|
25 | 25 |
from django.template.loader import TemplateDoesNotExist, get_template |
26 | 26 |
from django.utils.translation import gettext_lazy as _ |
27 | 27 | |
28 |
from combo import utils |
|
28 | 29 |
from combo.data.forms import get_page_choices |
29 | 30 |
from combo.data.models import Page, ParentContentCell, SiteSettings, compile_sub_slug |
30 | 31 | |
31 | 32 |
from .fields import ImageIncludingSvgField |
32 | 33 | |
33 | 34 | |
35 |
@utils.cache_during_request |
|
34 | 36 |
def get_groups_as_choices(): |
35 | 37 |
return [(x.id, x.name) for x in Group.objects.all().order_by('name')] |
36 | 38 |
combo/manager/views.py | ||
---|---|---|
419 | 419 | |
420 | 420 |
def get_context_data(self, **kwargs): |
421 | 421 |
context = super().get_context_data(**kwargs) |
422 |
cells = CellBase.get_cells(page=self.object, prefetch_validity_info=True) |
|
422 |
cells = CellBase.get_cells( |
|
423 |
page=self.object, |
|
424 |
prefetch_validity_info=True, |
|
425 |
prefetch_groups=True, |
|
426 |
select_related={'__all__': ['page']}, |
|
427 |
) |
|
423 | 428 |
existing_cell_types = {cell.get_cell_type_str() for cell in cells} |
424 | 429 |
cell_type_groups = {} |
425 | 430 |
for cell_type in CellBase.get_all_cell_types(): |
combo/settings.py | ||
---|---|---|
274 | 274 |
JSON_CELL_TYPES = {} |
275 | 275 | |
276 | 276 |
# dashboard support |
277 |
COMBO_DASHBOARD_ENABLED = True
|
|
277 |
COMBO_DASHBOARD_ENABLED = False
|
|
278 | 278 | |
279 | 279 |
COMBO_DASHBOARD_NEW_TILE_POSITION = 'last' |
280 | 280 |
tests/test_manager.py | ||
---|---|---|
702 | 702 |
app.get('/manage/pages/%s/' % page.pk) # load once to populate caches |
703 | 703 |
with CaptureQueriesContext(connection) as ctx: |
704 | 704 |
app.get('/manage/pages/%s/' % page.pk) |
705 |
assert len(ctx.captured_queries) == 44
|
|
705 |
assert len(ctx.captured_queries) == 40
|
|
706 | 706 | |
707 | 707 | |
708 | 708 |
def test_delete_page(app, admin_user): |
... | ... | |
2557 | 2557 |
resp = resp.click('restore', index=6) |
2558 | 2558 |
with CaptureQueriesContext(connection) as ctx: |
2559 | 2559 |
resp = resp.form.submit().follow() |
2560 |
assert len(ctx.captured_queries) == 153
|
|
2560 |
assert len(ctx.captured_queries) == 147
|
|
2561 | 2561 | |
2562 | 2562 |
resp2 = resp.click('See online') |
2563 | 2563 |
assert resp2.text.index('Foobar1') < resp2.text.index('Foobar2') < resp2.text.index('Foobar3') |
tests/wcs/test_card.py | ||
---|---|---|
686 | 686 |
assert resp.forms[0]['c%s-related_card_path' % cell.get_reference()].options == [ |
687 | 687 |
('__all__', False, 'All cards'), |
688 | 688 |
('--', True, 'Card whose identifier is in the URL'), |
689 |
('sluge-bis/cardd-bar/carde-foo', False, 'Linked card (From cell sluge-bis): "Card D" -> "Card E"'), |
|
689 | 690 |
( |
690 | 691 |
'sluge-again/cardd-bar/carde-foo', |
691 | 692 |
False, |
692 | 693 |
'Linked card (From cell sluge-again): "Card D" -> "Card E"', |
693 | 694 |
), |
694 |
('sluge-bis/cardd-bar/carde-foo', False, 'Linked card (From cell sluge-bis): "Card D" -> "Card E"'), |
|
695 | 695 |
('', False, 'Template'), |
696 | 696 |
] |
697 | 697 |
assert resp.forms[1]['c%s-related_card_path' % cell2.get_reference()].options == [ |
698 | 698 |
('__all__', False, 'All cards'), |
699 | 699 |
('--', True, 'Card whose identifier is in the URL'), |
700 |
('sluge/cardd-bar/carde-foo', False, 'Linked card (From cell sluge): "Card D" -> "Card E"'), |
|
700 | 701 |
( |
701 | 702 |
'sluge-again/cardd-bar/carde-foo', |
702 | 703 |
False, |
703 | 704 |
'Linked card (From cell sluge-again): "Card D" -> "Card E"', |
704 | 705 |
), |
705 |
('sluge/cardd-bar/carde-foo', False, 'Linked card (From cell sluge): "Card D" -> "Card E"'), |
|
706 | 706 |
('', False, 'Template'), |
707 | 707 |
] |
708 | 708 | |
709 |
- |