mirror of
https://github.com/pretix/pretix.git
synced 2026-05-07 15:34:02 +00:00
Allow plugins to filter subevents in the public calendar (#5457)
* Allow plugins to filter subevents in the public calendar * Add to docs * Review notes
This commit is contained in:
@@ -37,7 +37,7 @@ Frontend
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
.. automodule:: pretix.presale.signals
|
.. automodule:: pretix.presale.signals
|
||||||
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header, seatingframe_html_head
|
:members: html_head, html_footer, footer_link, global_footer_link, front_page_top, front_page_bottom, front_page_bottom_widget, fee_calculation_for_cart, contact_form_fields, question_form_fields, contact_form_fields_overrides, question_form_fields_overrides, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional, html_page_header, render_seating_plan, checkout_flow_steps, position_info, position_info_top, item_description, global_html_head, global_html_footer, global_html_page_header, seatingframe_html_head, filter_subevents
|
||||||
|
|
||||||
|
|
||||||
.. automodule:: pretix.presale.signals
|
.. automodule:: pretix.presale.signals
|
||||||
|
|||||||
@@ -415,3 +415,19 @@ consent state. Receivers should return a list of ``pretix.presale.cookies.Cookie
|
|||||||
|
|
||||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
filter_subevents = GlobalSignal()
|
||||||
|
"""
|
||||||
|
Arguments: ``subevents``, ``sales_channel``
|
||||||
|
|
||||||
|
This signal allows you to filter which subevents are publicly available. Receivers are passed a
|
||||||
|
list of subevents that are about to be shown to the user and are expected to return a list of the
|
||||||
|
same format, with all subevents removed that should not be available for sale.
|
||||||
|
|
||||||
|
``sales_channels`` is a ``SalesChannel`` instance.
|
||||||
|
|
||||||
|
This is not an event-plugin signal as this will also be called on the organizer level when showing
|
||||||
|
a list of subevents across events. Expect that the subevents in the input are mixed from different
|
||||||
|
events. However, receivers will only receive subevents of events that the plugin is active for and
|
||||||
|
can only filter out these.
|
||||||
|
"""
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ from pretix.presale.ical import get_public_ical
|
|||||||
from pretix.presale.signals import item_description, seatingframe_html_head
|
from pretix.presale.signals import item_description, seatingframe_html_head
|
||||||
from pretix.presale.views.organizer import (
|
from pretix.presale.views.organizer import (
|
||||||
EventListMixin, add_subevents_for_days, days_for_template,
|
EventListMixin, add_subevents_for_days, days_for_template,
|
||||||
filter_qs_by_attr, has_before_after, weeks_for_template,
|
filter_qs_by_attr, filter_subevents_with_plugins, has_before_after,
|
||||||
|
weeks_for_template,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
@@ -546,6 +547,12 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
|
|||||||
self.subevent = request.event.subevents.using(settings.DATABASE_REPLICA).filter(pk=kwargs['subevent'], active=True).first()
|
self.subevent = request.event.subevents.using(settings.DATABASE_REPLICA).filter(pk=kwargs['subevent'], active=True).first()
|
||||||
if not self.subevent:
|
if not self.subevent:
|
||||||
raise Http404()
|
raise Http404()
|
||||||
|
|
||||||
|
# Prevent direct access to subevents that are hidden by a plugin
|
||||||
|
subevents = filter_subevents_with_plugins([self.subevent], self.request.sales_channel)
|
||||||
|
if self.subevent not in subevents:
|
||||||
|
raise Http404()
|
||||||
|
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
@@ -703,9 +710,14 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
|
|||||||
).using(settings.DATABASE_REPLICA),
|
).using(settings.DATABASE_REPLICA),
|
||||||
self.request
|
self.request
|
||||||
),
|
),
|
||||||
limit_before, after, ebd, set(), self.request.event,
|
before=limit_before,
|
||||||
self.kwargs.get('cart_namespace'),
|
after=after,
|
||||||
voucher,
|
ebd=ebd,
|
||||||
|
timezones=set(),
|
||||||
|
event=self.request.event,
|
||||||
|
cart_namespace=self.kwargs.get('cart_namespace'),
|
||||||
|
voucher=voucher,
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Hide names of subevents in event series where it is always the same. No need to show the name of the museum thousands of times
|
# Hide names of subevents in event series where it is always the same. No need to show the name of the museum thousands of times
|
||||||
@@ -762,9 +774,14 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
|
|||||||
).using(settings.DATABASE_REPLICA),
|
).using(settings.DATABASE_REPLICA),
|
||||||
self.request
|
self.request
|
||||||
),
|
),
|
||||||
limit_before, after, ebd, set(), self.request.event,
|
before=limit_before,
|
||||||
self.kwargs.get('cart_namespace'),
|
after=after,
|
||||||
voucher,
|
ebd=ebd,
|
||||||
|
timezones=set(),
|
||||||
|
event=self.request.event,
|
||||||
|
cart_namespace=self.kwargs.get('cart_namespace'),
|
||||||
|
voucher=voucher,
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Hide names of subevents in event series where it is always the same. No need to show the name of the museum thousands of times
|
# Hide names of subevents in event series where it is always the same. No need to show the name of the museum thousands of times
|
||||||
@@ -803,7 +820,7 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
|
|||||||
future_only=self.request.event.settings.event_calendar_future_only
|
future_only=self.request.event.settings.event_calendar_future_only
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
context['subevent_list'] = self.request.event.subevents_sorted(
|
subevents = self.request.event.subevents_sorted(
|
||||||
filter_qs_by_attr(
|
filter_qs_by_attr(
|
||||||
self.request.event.subevents_annotated(
|
self.request.event.subevents_annotated(
|
||||||
self.request.sales_channel,
|
self.request.sales_channel,
|
||||||
@@ -812,12 +829,14 @@ class EventIndex(EventViewMixin, EventListMixin, CartMixin, TemplateView):
|
|||||||
self.request
|
self.request
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
subevents = filter_subevents_with_plugins(list(subevents), self.request.sales_channel)
|
||||||
|
context['subevent_list'] = subevents
|
||||||
if self.request.event.settings.event_list_available_only and not voucher:
|
if self.request.event.settings.event_list_available_only and not voucher:
|
||||||
context['subevent_list'] = [
|
context['subevent_list'] = [
|
||||||
se for se in context['subevent_list']
|
se for se in subevents
|
||||||
if not se.presale_has_ended and (se.best_availability_state is None or se.best_availability_state >= Quota.AVAILABILITY_RESERVED)
|
if not se.presale_has_ended and (se.best_availability_state is None or se.best_availability_state >= Quota.AVAILABILITY_RESERVED)
|
||||||
]
|
]
|
||||||
context['visible_events'] = len(context['subevent_list']) > 0
|
context['visible_events'] = len(subevents) > 0
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ from django.db.models import (
|
|||||||
Case, Exists, F, Max, Min, OuterRef, Prefetch, Q, Value, When,
|
Case, Exists, F, Max, Min, OuterRef, Prefetch, Q, Value, When,
|
||||||
)
|
)
|
||||||
from django.db.models.functions import Coalesce, Greatest
|
from django.db.models.functions import Coalesce, Greatest
|
||||||
|
from django.dispatch.dispatcher import NO_RECEIVERS
|
||||||
from django.http import Http404, HttpResponse, QueryDict
|
from django.http import Http404, HttpResponse, QueryDict
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
@@ -76,6 +77,7 @@ from pretix.helpers.thumb import get_thumbnail
|
|||||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||||
from pretix.presale.forms.organizer import EventListFilterForm
|
from pretix.presale.forms.organizer import EventListFilterForm
|
||||||
from pretix.presale.ical import get_public_ical
|
from pretix.presale.ical import get_public_ical
|
||||||
|
from pretix.presale.signals import filter_subevents
|
||||||
from pretix.presale.views import OrganizerViewMixin
|
from pretix.presale.views import OrganizerViewMixin
|
||||||
|
|
||||||
|
|
||||||
@@ -561,16 +563,56 @@ def add_events_for_days(request, baseqs, before, after, ebd, timezones):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_namespace=None, voucher=None):
|
def filter_subevents_with_plugins(subevents, sales_channel=None):
|
||||||
|
# Special-case of GlobalSignal.send_chained() that only sends subevents that have the plugin enabled
|
||||||
|
# and then mixes the results back together.
|
||||||
|
from pretix.base.signals import (
|
||||||
|
_populate_app_cache, app_cache, get_defining_app, is_app_active,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not filter_subevents.receivers or filter_subevents.sender_receivers_cache.get(None) is NO_RECEIVERS:
|
||||||
|
return subevents
|
||||||
|
|
||||||
|
if not app_cache:
|
||||||
|
_populate_app_cache()
|
||||||
|
|
||||||
|
for receiver in filter_subevents._live_receivers(None):
|
||||||
|
app = get_defining_app(receiver)
|
||||||
|
event_state = {}
|
||||||
|
|
||||||
|
def app_active(event):
|
||||||
|
if event.pk not in event_state:
|
||||||
|
event_state[event.pk] = is_app_active(event, app, allow_legacy_plugins=True)
|
||||||
|
return event_state[event.pk]
|
||||||
|
|
||||||
|
subevents_passed_to_receiver = [
|
||||||
|
s for s in subevents if app_active(s.event)
|
||||||
|
]
|
||||||
|
response = receiver(
|
||||||
|
signal=filter_subevents,
|
||||||
|
sender=None,
|
||||||
|
subevents=subevents_passed_to_receiver,
|
||||||
|
sales_channel=sales_channel,
|
||||||
|
)
|
||||||
|
subevents = [
|
||||||
|
s for s in subevents if s in response or s not in subevents_passed_to_receiver
|
||||||
|
]
|
||||||
|
|
||||||
|
return subevents
|
||||||
|
|
||||||
|
|
||||||
|
def add_subevents_for_days(qs, before, after, ebd, timezones, sales_channel, event=None, cart_namespace=None,
|
||||||
|
voucher=None):
|
||||||
qs = qs.filter(active=True, is_public=True).filter(
|
qs = qs.filter(active=True, is_public=True).filter(
|
||||||
Q(Q(date_to__gte=before) & Q(date_from__lte=after)) |
|
Q(Q(date_to__gte=before) & Q(date_from__lte=after)) |
|
||||||
Q(Q(date_to__isnull=True) & Q(date_from__gte=before) & Q(date_from__lte=after))
|
Q(Q(date_to__isnull=True) & Q(date_from__gte=before) & Q(date_from__lte=after))
|
||||||
).order_by(
|
).order_by(
|
||||||
'date_from'
|
'date_from'
|
||||||
)
|
)
|
||||||
|
subevents = filter_subevents_with_plugins(list(qs), sales_channel)
|
||||||
|
|
||||||
quotas_to_compute = []
|
quotas_to_compute = []
|
||||||
for se in qs:
|
for se in subevents:
|
||||||
if se.presale_is_running:
|
if se.presale_is_running:
|
||||||
quotas_to_compute += se.active_quotas
|
quotas_to_compute += se.active_quotas
|
||||||
for q in se.active_quotas:
|
for q in se.active_quotas:
|
||||||
@@ -588,7 +630,7 @@ def add_subevents_for_days(qs, before, after, ebd, timezones, event=None, cart_n
|
|||||||
qa.compute(allow_cache=True)
|
qa.compute(allow_cache=True)
|
||||||
qcache.update(qa.results)
|
qcache.update(qa.results)
|
||||||
|
|
||||||
for se in qs:
|
for se in subevents:
|
||||||
if qcache:
|
if qcache:
|
||||||
se._quota_cache = qcache
|
se._quota_cache = qcache
|
||||||
if event is not None: # save database lookup later
|
if event is not None: # save database lookup later
|
||||||
@@ -763,24 +805,31 @@ class CalendarView(OrganizerViewMixin, EventListMixin, TemplateView):
|
|||||||
).filter(
|
).filter(
|
||||||
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
||||||
), before, after, ebd, timezones)
|
), before, after, ebd, timezones)
|
||||||
add_subevents_for_days(filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
add_subevents_for_days(
|
||||||
Q(event__all_sales_channels=True) |
|
filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
||||||
Q(event__limit_sales_channels=self.request.sales_channel),
|
Q(event__all_sales_channels=True) |
|
||||||
event__organizer=self.request.organizer,
|
Q(event__limit_sales_channels=self.request.sales_channel),
|
||||||
event__is_public=True,
|
event__organizer=self.request.organizer,
|
||||||
event__live=True,
|
event__is_public=True,
|
||||||
).prefetch_related(
|
event__live=True,
|
||||||
Prefetch(
|
).prefetch_related(
|
||||||
'event',
|
Prefetch(
|
||||||
queryset=Event.objects.prefetch_related(
|
'event',
|
||||||
'_settings_objects',
|
queryset=Event.objects.prefetch_related(
|
||||||
Prefetch(
|
'_settings_objects',
|
||||||
'organizer',
|
Prefetch(
|
||||||
queryset=Organizer.objects.prefetch_related('_settings_objects')
|
'organizer',
|
||||||
|
queryset=Organizer.objects.prefetch_related('_settings_objects')
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
), self.request.sales_channel), self.request).using(settings.DATABASE_REPLICA),
|
||||||
), self.request.sales_channel), self.request).using(settings.DATABASE_REPLICA), before, after, ebd, timezones)
|
before=before,
|
||||||
|
after=after,
|
||||||
|
ebd=ebd,
|
||||||
|
timezones=timezones,
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
|
)
|
||||||
self._multiple_timezones = len(timezones) > 1
|
self._multiple_timezones = len(timezones) > 1
|
||||||
return ebd
|
return ebd
|
||||||
|
|
||||||
@@ -860,24 +909,31 @@ class WeekCalendarView(OrganizerViewMixin, EventListMixin, TemplateView):
|
|||||||
).filter(
|
).filter(
|
||||||
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
||||||
), before, after, ebd, timezones)
|
), before, after, ebd, timezones)
|
||||||
add_subevents_for_days(filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
add_subevents_for_days(
|
||||||
Q(event__all_sales_channels=True) |
|
filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
||||||
Q(event__limit_sales_channels=self.request.sales_channel),
|
Q(event__all_sales_channels=True) |
|
||||||
event__organizer=self.request.organizer,
|
Q(event__limit_sales_channels=self.request.sales_channel),
|
||||||
event__is_public=True,
|
event__organizer=self.request.organizer,
|
||||||
event__live=True,
|
event__is_public=True,
|
||||||
).prefetch_related(
|
event__live=True,
|
||||||
Prefetch(
|
).prefetch_related(
|
||||||
'event',
|
Prefetch(
|
||||||
queryset=Event.objects.prefetch_related(
|
'event',
|
||||||
'_settings_objects',
|
queryset=Event.objects.prefetch_related(
|
||||||
Prefetch(
|
'_settings_objects',
|
||||||
'organizer',
|
Prefetch(
|
||||||
queryset=Organizer.objects.prefetch_related('_settings_objects')
|
'organizer',
|
||||||
|
queryset=Organizer.objects.prefetch_related('_settings_objects')
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
), self.request.sales_channel), self.request).using(settings.DATABASE_REPLICA),
|
||||||
), self.request.sales_channel), self.request).using(settings.DATABASE_REPLICA), before, after, ebd, timezones)
|
before=before,
|
||||||
|
after=after,
|
||||||
|
ebd=ebd,
|
||||||
|
timezones=timezones,
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
|
)
|
||||||
self._multiple_timezones = len(timezones) > 1
|
self._multiple_timezones = len(timezones) > 1
|
||||||
return ebd
|
return ebd
|
||||||
|
|
||||||
@@ -1211,24 +1267,31 @@ class DayCalendarView(OrganizerViewMixin, EventListMixin, TemplateView):
|
|||||||
).filter(
|
).filter(
|
||||||
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
||||||
), before, after, ebd, timezones)
|
), before, after, ebd, timezones)
|
||||||
add_subevents_for_days(filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
add_subevents_for_days(
|
||||||
Q(event__all_sales_channels=True) |
|
filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
||||||
Q(event__limit_sales_channels=self.request.sales_channel),
|
Q(event__all_sales_channels=True) |
|
||||||
event__organizer=self.request.organizer,
|
Q(event__limit_sales_channels=self.request.sales_channel),
|
||||||
event__is_public=True,
|
event__organizer=self.request.organizer,
|
||||||
event__live=True,
|
event__is_public=True,
|
||||||
).prefetch_related(
|
event__live=True,
|
||||||
Prefetch(
|
).prefetch_related(
|
||||||
'event',
|
Prefetch(
|
||||||
queryset=Event.objects.prefetch_related(
|
'event',
|
||||||
'_settings_objects',
|
queryset=Event.objects.prefetch_related(
|
||||||
Prefetch(
|
'_settings_objects',
|
||||||
'organizer',
|
Prefetch(
|
||||||
queryset=Organizer.objects.prefetch_related('_settings_objects')
|
'organizer',
|
||||||
|
queryset=Organizer.objects.prefetch_related('_settings_objects')
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
), self.request.sales_channel), self.request).using(settings.DATABASE_REPLICA),
|
||||||
), self.request.sales_channel), self.request).using(settings.DATABASE_REPLICA), before, after, ebd, timezones)
|
before=before,
|
||||||
|
after=after,
|
||||||
|
ebd=ebd,
|
||||||
|
timezones=timezones,
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
|
)
|
||||||
self._multiple_timezones = len(timezones) > 1
|
self._multiple_timezones = len(timezones) > 1
|
||||||
return ebd
|
return ebd
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ from pretix.presale.views.event import (
|
|||||||
)
|
)
|
||||||
from pretix.presale.views.organizer import (
|
from pretix.presale.views.organizer import (
|
||||||
EventListMixin, add_events_for_days, add_subevents_for_days,
|
EventListMixin, add_events_for_days, add_subevents_for_days,
|
||||||
days_for_template, filter_qs_by_attr, weeks_for_template,
|
days_for_template, filter_qs_by_attr, filter_subevents_with_plugins,
|
||||||
|
weeks_for_template,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -403,6 +404,14 @@ class WidgetAPIProductList(EventListMixin, View):
|
|||||||
return self.response({
|
return self.response({
|
||||||
'error': gettext('The selected date does not exist in this event series.')
|
'error': gettext('The selected date does not exist in this event series.')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Prevent direct access to subevents that are hidden by a plugin
|
||||||
|
subevents = filter_subevents_with_plugins([self.subevent], request.sales_channel)
|
||||||
|
if self.subevent not in subevents:
|
||||||
|
return self.response({
|
||||||
|
'error': gettext('The selected date is not available.')
|
||||||
|
})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return self._get_event_list(request, **kwargs)
|
return self._get_event_list(request, **kwargs)
|
||||||
else:
|
else:
|
||||||
@@ -568,8 +577,9 @@ class WidgetAPIProductList(EventListMixin, View):
|
|||||||
Q(event__limit_sales_channels=self.request.sales_channel),
|
Q(event__limit_sales_channels=self.request.sales_channel),
|
||||||
), self.request
|
), self.request
|
||||||
),
|
),
|
||||||
limit_before, after, ebd, set(), self.request.event,
|
before=limit_before, after=after, ebd=ebd, timezones=set(), event=self.request.event,
|
||||||
kwargs.get('cart_namespace')
|
cart_namespace=kwargs.get('cart_namespace'),
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
timezones = set()
|
timezones = set()
|
||||||
@@ -580,17 +590,27 @@ class WidgetAPIProductList(EventListMixin, View):
|
|||||||
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
Q(all_sales_channels=True) | Q(limit_sales_channels=self.request.sales_channel),
|
||||||
), self.request
|
), self.request
|
||||||
),
|
),
|
||||||
limit_before, after, ebd, timezones
|
before=limit_before,
|
||||||
|
after=after,
|
||||||
|
ebd=ebd,
|
||||||
|
timezones=timezones,
|
||||||
|
)
|
||||||
|
add_subevents_for_days(
|
||||||
|
filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
||||||
|
Q(event__all_sales_channels=True) |
|
||||||
|
Q(event__limit_sales_channels__identifier=self.request.sales_channel.identifier),
|
||||||
|
event__organizer=self.request.organizer,
|
||||||
|
event__is_public=True,
|
||||||
|
event__live=True,
|
||||||
|
).prefetch_related(
|
||||||
|
'event___settings_objects', 'event__organizer___settings_objects'
|
||||||
|
), self.request.sales_channel), self.request),
|
||||||
|
before=limit_before,
|
||||||
|
after=after,
|
||||||
|
ebd=ebd,
|
||||||
|
timezones=timezones,
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
)
|
)
|
||||||
add_subevents_for_days(filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
|
||||||
Q(event__all_sales_channels=True) |
|
|
||||||
Q(event__limit_sales_channels__identifier=self.request.sales_channel.identifier),
|
|
||||||
event__organizer=self.request.organizer,
|
|
||||||
event__is_public=True,
|
|
||||||
event__live=True,
|
|
||||||
).prefetch_related(
|
|
||||||
'event___settings_objects', 'event__organizer___settings_objects'
|
|
||||||
), self.request.sales_channel), self.request), limit_before, after, ebd, timezones)
|
|
||||||
|
|
||||||
data['weeks'] = weeks_for_template(ebd, self.year, self.month)
|
data['weeks'] = weeks_for_template(ebd, self.year, self.month)
|
||||||
for w in data['weeks']:
|
for w in data['weeks']:
|
||||||
@@ -624,8 +644,9 @@ class WidgetAPIProductList(EventListMixin, View):
|
|||||||
if hasattr(self.request, 'event'):
|
if hasattr(self.request, 'event'):
|
||||||
add_subevents_for_days(
|
add_subevents_for_days(
|
||||||
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel), self.request),
|
filter_qs_by_attr(self.request.event.subevents_annotated(self.request.sales_channel), self.request),
|
||||||
limit_before, after, ebd, set(), self.request.event,
|
before=limit_before, after=after, ebd=ebd, timezones=set(), event=self.request.event,
|
||||||
kwargs.get('cart_namespace')
|
cart_namespace=kwargs.get('cart_namespace'),
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
timezones = set()
|
timezones = set()
|
||||||
@@ -634,13 +655,20 @@ class WidgetAPIProductList(EventListMixin, View):
|
|||||||
filter_qs_by_attr(Event.annotated(self.request.organizer.events, self.request.sales_channel), self.request),
|
filter_qs_by_attr(Event.annotated(self.request.organizer.events, self.request.sales_channel), self.request),
|
||||||
limit_before, after, ebd, timezones
|
limit_before, after, ebd, timezones
|
||||||
)
|
)
|
||||||
add_subevents_for_days(filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
add_subevents_for_days(
|
||||||
event__organizer=self.request.organizer,
|
filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter(
|
||||||
event__is_public=True,
|
event__organizer=self.request.organizer,
|
||||||
event__live=True,
|
event__is_public=True,
|
||||||
).prefetch_related(
|
event__live=True,
|
||||||
'event___settings_objects', 'event__organizer___settings_objects'
|
).prefetch_related(
|
||||||
), self.request.sales_channel), self.request), limit_before, after, ebd, timezones)
|
'event___settings_objects', 'event__organizer___settings_objects'
|
||||||
|
), self.request.sales_channel), self.request),
|
||||||
|
before=limit_before,
|
||||||
|
after=after,
|
||||||
|
ebd=ebd,
|
||||||
|
timezones=timezones,
|
||||||
|
sales_channel=self.request.sales_channel,
|
||||||
|
)
|
||||||
|
|
||||||
data['days'] = days_for_template(ebd, week)
|
data['days'] = days_for_template(ebd, week)
|
||||||
for d in data['days']:
|
for d in data['days']:
|
||||||
|
|||||||
Reference in New Issue
Block a user