api: prefetch exceptions for recurring events (#50561)

This commit is contained in:
Valentin Deniaud 2021-02-04 15:10:29 +01:00
parent 80826930ed
commit 6aa49605cc
3 changed files with 30 additions and 7 deletions

View File

@ -660,10 +660,11 @@ class Agenda(models.Model):
if prefetched_queryset:
recurring_events = self.prefetched_recurring_events
exceptions = self.prefetched_exceptions
else:
recurring_events = self.event_set.filter(recurrence_rule__isnull=False)
exceptions = self.get_recurrence_exceptions(min_start, max_start)
exceptions = self.get_recurrence_exceptions(min_start, max_start)
for event in recurring_events:
events.extend(
event.get_recurrences(

View File

@ -565,6 +565,9 @@ class Agendas(APIView):
start_datetime__gte=localtime(now()),
).order_by()
recurring_event_queryset = Event.objects.filter(recurrence_rule__isnull=False)
exceptions_desk = Desk.objects.filter(slug='_exceptions_holder').prefetch_related(
'unavailability_calendars'
)
agendas_queryset = agendas_queryset.filter(kind='events').prefetch_related(
Prefetch(
'event_set',
@ -576,15 +579,34 @@ class Agendas(APIView):
queryset=recurring_event_queryset,
to_attr='prefetched_recurring_events',
),
Prefetch(
'desk_set',
queryset=exceptions_desk,
to_attr='prefetched_desks',
),
)
agendas_exceptions = TimePeriodException.objects.filter(
Q(desk__slug='_exceptions_holder', desk__agenda__in=agendas_queryset)
| Q(
unavailability_calendar__desks__slug='_exceptions_holder',
unavailability_calendar__desks__agenda__in=agendas_queryset,
),
start_datetime__gte=localtime(now()),
)
agendas = []
for agenda in agendas_queryset:
if with_open_events and not any(
not e.full for e in agenda.get_open_events(prefetched_queryset=True)
):
# exclude agendas without open events
continue
if with_open_events:
desk = agenda.prefetched_desks[0]
uc_ids = [uc.pk for uc in desk.unavailability_calendars.all()]
agenda.prefetched_exceptions = [
e
for e in agendas_exceptions
if e.desk_id == desk.pk or e.unavailability_calendar_id in uc_ids
]
if not any(not e.full for e in agenda.get_open_events(prefetched_queryset=True)):
# exclude agendas without open events
continue
agendas.append(get_agenda_detail(request, agenda))
return Response({'data': agendas})

View File

@ -317,7 +317,7 @@ def test_agendas_api(app):
with CaptureQueriesContext(connection) as ctx:
resp = app.get('/api/agenda/', params={'with_open_events': '1'})
assert len(ctx.captured_queries) == 15
assert len(ctx.captured_queries) == 7
def test_agendas_meetingtypes_api(app, some_data, meetings_agenda):