From ae16c15f00b58e28286c50ea0eccf20c16bf12b0 Mon Sep 17 00:00:00 2001 From: Chatewgne Date: Tue, 20 Aug 2024 18:06:47 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20[PERF]=20Optimize=20some=20queries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/changelog.rst | 1 + geotrek/land/filters.py | 14 ++++++++++---- geotrek/land/models.py | 4 ++-- geotrek/maintenance/filters.py | 4 ++++ geotrek/outdoor/templatetags/outdoor_tags.py | 4 ++-- geotrek/tourism/filters.py | 4 ++-- geotrek/tourism/templatetags/tourism_tags.py | 6 +++--- geotrek/trekking/models.py | 2 +- geotrek/trekking/templatetags/trekking_tags.py | 2 +- geotrek/trekking/views.py | 4 ++-- 10 files changed, 28 insertions(+), 17 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 2c2bfee0d6..0df29af91f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -20,6 +20,7 @@ CHANGELOG **Maintenance** - Replace deprecated `env_file` with `dotenv` +- Optimize some backend queries for performances 2.109.0 (2024-08-08) diff --git a/geotrek/land/filters.py b/geotrek/land/filters.py index 3ed513cc08..40a6679097 100644 --- a/geotrek/land/filters.py +++ b/geotrek/land/filters.py @@ -63,28 +63,34 @@ class Meta(OrganismFilterSet.Meta): """ -class TopologyFilterPhysicalType(TopologyFilter): +class PrefetchStructureMixin: + def get_queryset(self, request=None): + qs = super().get_queryset(request) + return qs.select_related('structure') + + +class TopologyFilterPhysicalType(PrefetchStructureMixin, TopologyFilter): model = PhysicalType def values_to_edges(self, values): return PhysicalEdge.objects.filter(physical_type__in=values) -class TopologyFilterCirculationType(TopologyFilter): +class TopologyFilterCirculationType(PrefetchStructureMixin, TopologyFilter): model = CirculationType def values_to_edges(self, values): return CirculationEdge.objects.filter(circulation_type__in=values) -class TopologyFilterAuthorizationType(TopologyFilter): +class TopologyFilterAuthorizationType(PrefetchStructureMixin, TopologyFilter): model = AuthorizationType def values_to_edges(self, values): return CirculationEdge.objects.filter(authorization_type__in=values) -class TopologyFilterLandType(TopologyFilter): +class TopologyFilterLandType(PrefetchStructureMixin, TopologyFilter): model = LandType def values_to_edges(self, values): diff --git a/geotrek/land/models.py b/geotrek/land/models.py index 4e313bd2df..dea96e8eca 100644 --- a/geotrek/land/models.py +++ b/geotrek/land/models.py @@ -80,11 +80,11 @@ def physical_type_csv_display(self): @classmethod def path_physicals(cls, path): - return cls.objects.existing().select_related('physical_type').filter(aggregations__path=path).distinct('pk') + return cls.objects.existing().select_related('physical_type', 'physical_type__structure').filter(aggregations__path=path).distinct('pk') @classmethod def topology_physicals(cls, topology): - return cls.overlapping(topology).select_related('physical_type') + return cls.overlapping(topology).select_related('physical_type', 'physical_type__structure') @receiver(pre_delete, sender=Topology) diff --git a/geotrek/maintenance/filters.py b/geotrek/maintenance/filters.py index e47f59cfaa..a60bf01d92 100644 --- a/geotrek/maintenance/filters.py +++ b/geotrek/maintenance/filters.py @@ -105,6 +105,10 @@ class ProjectIntersectionFilterDistrict(PolygonProjectFilterMixin, RightFilter): class ProjectIntersectionFilterRestrictedArea(PolygonProjectFilterMixin, RightFilter): model = RestrictedArea + def get_queryset(self, request=None): + qs = super().get_queryset(request) + return qs.select_related('area_type') + class ProjectIntersectionFilterRestrictedAreaType(PolygonProjectFilterMixin, RightFilter): model = RestrictedAreaType diff --git a/geotrek/outdoor/templatetags/outdoor_tags.py b/geotrek/outdoor/templatetags/outdoor_tags.py index 3aebcb08a6..9bc26172d0 100644 --- a/geotrek/outdoor/templatetags/outdoor_tags.py +++ b/geotrek/outdoor/templatetags/outdoor_tags.py @@ -25,7 +25,7 @@ def site_practices(): for scale in practice.rating_scales.all() }, } - for practice in Practice.objects.all() + for practice in Practice.objects.prefetch_related('site_types', 'rating_scales').all() } return json.dumps(practices) @@ -44,7 +44,7 @@ def course_sites(): for scale in site.practice.rating_scales.all() }, } if not (site.practice is None) else {'practice': None, 'types': {}, 'scales': {}} - for site in Site.objects.all() + for site in Site.objects.select_related('practice').prefetch_related('practice__course_types', 'practice__rating_scales').all() } return json.dumps(sites) diff --git a/geotrek/tourism/filters.py b/geotrek/tourism/filters.py index ef9f534791..051e161db6 100644 --- a/geotrek/tourism/filters.py +++ b/geotrek/tourism/filters.py @@ -25,8 +25,8 @@ class TypeFilter(ModelMultipleChoiceFilter): class TouristicContentFilterSet(ZoningFilterSet, StructureRelatedFilterSet): - type1 = TypeFilter(queryset=TouristicContentType1.objects.all()) - type2 = TypeFilter(queryset=TouristicContentType2.objects.all()) + type1 = TypeFilter(queryset=TouristicContentType1.objects.select_related('category').all()) + type2 = TypeFilter(queryset=TouristicContentType2.objects.select_related('category').all()) provider = ChoiceFilter( field_name='provider', empty_label=_("Provider"), diff --git a/geotrek/tourism/templatetags/tourism_tags.py b/geotrek/tourism/templatetags/tourism_tags.py index 27c731a01e..3265a306cf 100644 --- a/geotrek/tourism/templatetags/tourism_tags.py +++ b/geotrek/tourism/templatetags/tourism_tags.py @@ -18,15 +18,15 @@ def touristic_content_categories(): 'type2_label': category.type2_label, 'type1_values': { str(type.pk): type.label - for type in category.types.filter(in_list=1) + for type in category.types.all() if type.in_list == 1 }, 'type2_values': { str(type.pk): type.label - for type in category.types.filter(in_list=2) + for type in category.types.all() if type.in_list == 2 }, 'geometry_type': category.geometry_type } - for category in TouristicContentCategory.objects.all() + for category in TouristicContentCategory.objects.prefetch_related('types').all() } return json.dumps(categories) diff --git a/geotrek/trekking/models.py b/geotrek/trekking/models.py index ac03ae2e53..f744ccecc2 100755 --- a/geotrek/trekking/models.py +++ b/geotrek/trekking/models.py @@ -707,7 +707,7 @@ def topology_all_pois(cls, topology, queryset=None): Transform(F('geom'), settings.SRID))) qs = qs.order_by('locate') - return qs + return qs.select_related("type") @classmethod def outdoor_all_pois(cls, obj): diff --git a/geotrek/trekking/templatetags/trekking_tags.py b/geotrek/trekking/templatetags/trekking_tags.py index bbcf1867a3..ca33a1e9e4 100644 --- a/geotrek/trekking/templatetags/trekking_tags.py +++ b/geotrek/trekking/templatetags/trekking_tags.py @@ -16,7 +16,7 @@ def trek_practices(): for scale in practice.rating_scales.all() }, } - for practice in Practice.objects.all().prefetch_related('rating_scales') + for practice in Practice.objects.prefetch_related('rating_scales').all() } return json.dumps(practices) diff --git a/geotrek/trekking/views.py b/geotrek/trekking/views.py index 65721106dc..a9a5872510 100755 --- a/geotrek/trekking/views.py +++ b/geotrek/trekking/views.py @@ -96,7 +96,7 @@ def render_to_response(self, context): class TrekDetail(CompletenessMixin, MapEntityDetail): - queryset = Trek.objects.existing().select_related('topo_object').prefetch_related( + queryset = Trek.objects.existing().select_related('topo_object', 'structure').prefetch_related( Prefetch('view_points', queryset=HDViewPoint.objects.select_related('content_type', 'license')) ) @@ -292,7 +292,7 @@ class POIDetail(CompletenessMixin, MapEntityDetail): queryset = POI.objects.existing().prefetch_related( Prefetch('view_points', queryset=HDViewPoint.objects.select_related('content_type', 'license')) - ) + ).select_related('type') def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs)