kopia lustrzana https://github.com/wagtail/wagtail
Add parent page query optimisation in PageListingMixin if ParentPageColumn is used
rodzic
cc56f0b6ba
commit
ef2dad9dd9
|
@ -79,7 +79,7 @@ class TestContentTypeUse(WagtailTestUtils, TestCase):
|
|||
self.assertContains(response, delete_url)
|
||||
self.assertContains(response, "data-bulk-action-select-all-checkbox")
|
||||
|
||||
with self.assertNumQueries(38):
|
||||
with self.assertNumQueries(33):
|
||||
self.client.get(request_url)
|
||||
|
||||
def test_content_type_use_results(self):
|
||||
|
|
|
@ -56,6 +56,8 @@ class ParentPageColumn(Column):
|
|||
cell_template_name = "wagtailadmin/pages/listing/_parent_page_cell.html"
|
||||
|
||||
def get_value(self, instance):
|
||||
if parent := getattr(instance, "_parent_page", None):
|
||||
return parent
|
||||
return instance.get_parent()
|
||||
|
||||
|
||||
|
|
|
@ -265,6 +265,14 @@ class PageListingMixin:
|
|||
kwargs["actions_next_url"] = self.index_url
|
||||
return kwargs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
if any(isinstance(column, ParentPageColumn) for column in self.columns):
|
||||
Page.objects.annotate_parent_page(context["object_list"])
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class IndexView(PageListingMixin, generic.IndexView):
|
||||
template_name = "wagtailadmin/pages/index.html"
|
||||
|
@ -439,19 +447,12 @@ class ExplorableIndexView(IndexView):
|
|||
context = super().get_context_data(**kwargs)
|
||||
|
||||
if self.is_searching:
|
||||
# postprocess this page of results to annotate each result with its parent page
|
||||
parent_page_paths = {
|
||||
page.path[: -page.steplen] for page in context["object_list"]
|
||||
}
|
||||
parent_pages_by_path = {
|
||||
page.path: page
|
||||
for page in Page.objects.filter(path__in=parent_page_paths).specific()
|
||||
}
|
||||
Page.objects.annotate_parent_page(context["object_list"])
|
||||
for page in context["object_list"]:
|
||||
parent_page = parent_pages_by_path.get(page.path[: -page.steplen])
|
||||
# add annotation if parent page is found and is not the currently viewed parent
|
||||
if parent_page and parent_page != self.parent_page:
|
||||
page.annotated_parent_page = parent_page
|
||||
# to be used by PageTitleColumn instead of a dedicated ParentPageColumn
|
||||
if page._parent_page and page._parent_page != self.parent_page:
|
||||
page.annotated_parent_page = page._parent_page
|
||||
|
||||
context.update(
|
||||
{
|
||||
|
|
|
@ -235,6 +235,36 @@ class BasePageManager(models.Manager):
|
|||
|
||||
return self.get(path=common_parent_path)
|
||||
|
||||
def annotate_parent_page(self, pages):
|
||||
"""
|
||||
Annotates each page with its parent page. This is implemented as a
|
||||
manager-only method instead of a QuerySet method so it can be used with
|
||||
search results.
|
||||
|
||||
If given a QuerySet, this method will evaluate it. Only use this method
|
||||
when you are ready to consume the queryset, e.g. after pagination has
|
||||
been applied. This is typically done in the view's `get_context_data`
|
||||
using `context["object_list"]`.
|
||||
|
||||
This method does not return a new queryset, but modifies the existing one,
|
||||
to ensure any references to the queryset in the view's context are updated
|
||||
(e.g. when using `context_object_name`).
|
||||
"""
|
||||
parent_page_paths = {
|
||||
Page._get_parent_path_from_path(page.path) for page in pages
|
||||
}
|
||||
parent_pages_by_path = {
|
||||
page.path: page
|
||||
for page in Page.objects.filter(path__in=parent_page_paths).specific(
|
||||
defer=True
|
||||
)
|
||||
}
|
||||
for page in pages:
|
||||
parent_page = parent_pages_by_path.get(
|
||||
Page._get_parent_path_from_path(page.path)
|
||||
)
|
||||
page._parent_page = parent_page
|
||||
|
||||
|
||||
PageManager = BasePageManager.from_queryset(PageQuerySet)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue