From 9f7f2f2da5b3c842d18792ef03cb8b651bac26ea Mon Sep 17 00:00:00 2001 From: Struan Donald Date: Thu, 11 Jan 2024 10:51:40 +0000 Subject: [PATCH] reduce number of repeated queries move queries that get favourites and auto converted to methods that generate dicts hence one query for all rather than one query per data set --- hub/views/area.py | 49 +++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/hub/views/area.py b/hub/views/area.py index fbc70204a..a978a570b 100644 --- a/hub/views/area.py +++ b/hub/views/area.py @@ -1,6 +1,6 @@ from collections import defaultdict -from django.db.models import Count, OuterRef, Subquery +from django.db.models import Count from django.http import JsonResponse from django.shortcuts import get_object_or_404, redirect from django.views.generic import DetailView, TemplateView, View @@ -47,23 +47,31 @@ def get_object(self): def get_page_title(self): return self.object.name - def process_dataset(self, data_set): - fav_sq = Subquery( + def get_user_favourite_datasets(self): + favs = ( UserDataSets.objects.filter( - data_set_id=OuterRef("data_type__data_set__id"), user=self.request.user, ) .values("data_set_id") .annotate(is_favourite=Count("id")) .values("is_favourite") ) - data_type = DataType.objects.filter( - data_set=data_set, area_type=self.object.area_type - ).first() - auto_converted = False - if data_type is not None: - auto_converted = data_type.auto_converted + fav_map = {} + for fav in favs: + fav_map["fav.data_set_id"] = fav["is_favourite"] + + return fav_map + + def get_auto_convered_datasets(self): + auto_converted = {} + + for ds in DataType.objects.filter(area_type=self.object.area_type): + auto_converted[ds.data_set_id] = ds.auto_converted + + return auto_converted + + def process_dataset(self, data_set, favs, auto_converted): base_qs = AreaData.objects.filter( area=self.object, data_type__data_set=data_set, @@ -81,33 +89,26 @@ def process_dataset(self, data_set): "data_type": data_set.data_type, "featured": data_set.featured, "excluded_countries": data_set.exclude_countries, - "auto_converted": auto_converted, + "auto_converted": auto_converted.get(data_set.id, False), + "is_favourite": favs.get(data_set.id, False), } if data_set.is_range: data["is_range"] = True data_range = base_qs.select_related("data_type").order_by("data_type__name") - data["is_favourite"] = UserDataSets.objects.filter( - data_set=data_set, - user=self.request.user, - ).exists() d = data_range.all() if len(d) == 0: d = None data["data"] = d elif data_set.category == "opinion": - data_range = ( - base_qs.annotate(is_favourite=fav_sq) - .select_related("data_type") - .order_by("data_type__order", "data_type__label") + data_range = base_qs.select_related("data_type").order_by( + "data_type__order", "data_type__label" ) data["data"] = data_range.all() else: - area_data = base_qs.annotate(is_favourite=fav_sq).select_related( - "data_type" - ) + area_data = base_qs.select_related("data_type") if area_data: data["data"] = area_data[0] @@ -190,10 +191,12 @@ def get_context_data(self, **kwargs): categories = defaultdict(list) indexed_categories = defaultdict(dict) + favs = self.get_user_favourite_datasets() + auto_converted = self.get_auto_convered_datasets() for data_set in DataSet.objects.order_by("order", "label").filter( areas_available=self.object.area_type ): - data = self.process_dataset(data_set) + data = self.process_dataset(data_set, favs, auto_converted) if data.get("data", None) is not None and data["data"]: if data_set.category is not None: