From 840e45ea5f5aea0c0adc0d93abb486ea9b96cb96 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Wed, 19 Jan 2022 12:43:27 +0100 Subject: [PATCH] api: use date parameters to filter subscribed agendas more efficiently (#60064) --- chrono/api/serializers.py | 17 ++++++++++++++--- chrono/api/views.py | 8 ++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/chrono/api/serializers.py b/chrono/api/serializers.py index a11d3fea..e6ab2ee8 100644 --- a/chrono/api/serializers.py +++ b/chrono/api/serializers.py @@ -172,13 +172,17 @@ class StatisticsFiltersSerializer(serializers.Serializer): ) -class DateRangeSerializer(serializers.Serializer): +class DateRangeMixin(metaclass=serializers.SerializerMetaclass): datetime_formats = ['%Y-%m-%d', '%Y-%m-%d %H:%M', 'iso-8601'] date_start = serializers.DateTimeField(required=False, input_formats=datetime_formats) date_end = serializers.DateTimeField(required=False, input_formats=datetime_formats) +class DateRangeSerializer(DateRangeMixin, serializers.Serializer): + pass + + class DatetimesSerializer(DateRangeSerializer): min_places = serializers.IntegerField(min_value=1, default=1) user_external_id = serializers.CharField(required=False, max_length=250, allow_blank=True) @@ -200,7 +204,7 @@ class DatetimesSerializer(DateRangeSerializer): return attrs -class AgendaOrSubscribedSlugsMixin(metaclass=serializers.SerializerMetaclass): +class AgendaOrSubscribedSlugsMixin(DateRangeMixin): agendas = CommaSeparatedStringField( required=False, child=serializers.SlugField(max_length=160, allow_blank=False) ) @@ -222,9 +226,16 @@ class AgendaOrSubscribedSlugsMixin(metaclass=serializers.SerializerMetaclass): ) if 'subscribed' in attrs: - agendas = Agenda.objects.filter(subscriptions__user_external_id=user_external_id).distinct() + lookups = {'subscriptions__user_external_id': user_external_id} + if 'date_start' in attrs: + lookups['subscriptions__date_start__gte'] = attrs['date_start'] + if 'date_end' in attrs: + lookups['subscriptions__date_end__lt'] = attrs['date_end'] + agendas = Agenda.objects.filter(**lookups).distinct() + if attrs['subscribed'] != ['all']: agendas = agendas.filter(category__slug__in=attrs['subscribed']) + attrs['agendas'] = agendas attrs['agenda_slugs'] = [agenda.slug for agenda in agendas] else: diff --git a/chrono/api/views.py b/chrono/api/views.py index 11ec76c1..74242988 100644 --- a/chrono/api/views.py +++ b/chrono/api/views.py @@ -1603,10 +1603,6 @@ class RecurringFillslots(APIView): if not settings.ENABLE_RECURRING_EVENT_BOOKING: raise Http404() - start_datetime, end_datetime = get_start_and_end_datetime_from_request(request) - if not start_datetime or start_datetime < now(): - start_datetime = now() - serializer = serializers.RecurringFillslotsQueryStringSerializer( data=request.query_params, context={'user_external_id': request.data.get('user_external_id')} ) @@ -1614,6 +1610,10 @@ class RecurringFillslots(APIView): raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors) data = serializer.validated_data + start_datetime, end_datetime = data.get('date_start'), data.get('date_end') + if not start_datetime or start_datetime < now(): + start_datetime = now() + context = { 'allowed_agenda_slugs': data['agenda_slugs'], 'agendas': Agenda.prefetch_recurring_events(data['agendas']), -- 2.30.2