Skip to content

Commit d46499c

Browse files
committed
refactor: faire qu'un seul query pour toutes les villes/EPCIs au lieu d'en faire un pour chacun
1 parent 0b18eea commit d46499c

3 files changed

Lines changed: 51 additions & 4 deletions

File tree

back/dora/decoupage_administratif/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ def get_from_code(self, code):
3838
self._cache[code] = value
3939
return value
4040

41+
def warm_cache(self, codes):
42+
codes_to_fetch = {c.upper() for c in codes if c} - self._cache.keys()
43+
if not codes_to_fetch:
44+
return
45+
found = {obj.code.upper(): obj for obj in self.filter(code__in=codes_to_fetch)}
46+
for code in codes_to_fetch:
47+
self._cache[code] = found.get(code)
48+
4149

4250
# Cache instantané pour les tables comportant peu d'entités
4351
# on fait la requête une fois pour toute

back/dora/emplois/tests/test_emplois_views.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from model_bakery import baker
44

55
from dora.core.test_utils import make_published_service
6+
from dora.decoupage_administratif.models import AdminDivisionType, City
67

78

89
def test_services_api_requires_authentication(api_client):
@@ -66,14 +67,21 @@ def test_services_api_list_queries_are_bounded(
6667
api_client,
6768
django_assert_num_queries,
6869
):
69-
for _ in range(3):
70-
make_published_service()
70+
"""
71+
Il faut assurer qu'il n'y a qu'un seul query pour toutes les villes
72+
"""
73+
for i in range(5):
74+
city_code = f"7500{i}"
75+
baker.make(City, code=city_code, name="Paris")
76+
make_published_service(
77+
diffusion_zone_details=city_code, diffusion_zone_type=AdminDivisionType.CITY
78+
)
7179

72-
with django_assert_num_queries(11):
80+
with django_assert_num_queries(12):
7381
response = api_client.get(reverse("emplois:service-list"))
7482

7583
assert response.status_code == 200
76-
assert len(response.data) == 3
84+
assert len(response.data) == 5
7785

7886

7987
def test_services_api_detail_queries_are_bounded(

back/dora/emplois/views.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22
from django.db.models import Prefetch
33
from rest_framework import permissions, viewsets
44
from rest_framework.renderers import JSONRenderer
5+
from rest_framework.response import Response
56
from rest_framework.versioning import NamespaceVersioning
67

78
from dora.core.pagination import OptionalPageNumberPagination
9+
from dora.decoupage_administratif.models import (
10+
EPCI,
11+
AdminDivisionType,
12+
City,
13+
)
814
from dora.orientations.models import Orientation, OrientationStatus
915
from dora.services.models import Service
1016
from dora.structures.models import DisabledDoraFormDIStructure
@@ -58,6 +64,31 @@ def get_queryset(self):
5864
.order_by("pk")
5965
)
6066

67+
def _warm_geo_caches(self, services):
68+
city_codes = [
69+
s.diffusion_zone_details
70+
for s in services
71+
if s.diffusion_zone_type == AdminDivisionType.CITY
72+
]
73+
epci_codes = [
74+
s.diffusion_zone_details
75+
for s in services
76+
if s.diffusion_zone_type == AdminDivisionType.EPCI
77+
]
78+
City.objects.warm_cache(city_codes)
79+
EPCI.objects.warm_cache(epci_codes)
80+
81+
def list(self, request, *args, **kwargs):
82+
queryset = self.filter_queryset(self.get_queryset())
83+
page = self.paginate_queryset(queryset)
84+
if page is not None:
85+
self._warm_geo_caches(page)
86+
serializer = self.get_serializer(page, many=True)
87+
return self.get_paginated_response(serializer.data)
88+
self._warm_geo_caches(queryset)
89+
serializer = self.get_serializer(queryset, many=True)
90+
return Response(serializer.data)
91+
6192

6293
class DisabledDoraFormDIStructureViewSet(viewsets.ReadOnlyModelViewSet):
6394
versioning_class = NamespaceVersioning

0 commit comments

Comments
 (0)