def _get_event_list(self, request, **kwargs): data = {} o = getattr(request, 'event', request.organizer) list_type = self.request.GET.get("style", o.settings.event_list_type) data['list_type'] = list_type if hasattr(self.request, 'event') and data['list_type'] not in ("calendar", "week"): if self.request.event.subevents.filter( date_from__gt=now()).count() > 50: if self.request.event.settings.event_list_type not in ( "calendar", "week"): self.request.event.settings.event_list_type = "calendar" data['list_type'] = list_type = 'calendar' if hasattr(self.request, 'event'): data['name'] = str(request.event.name) data['frontpage_text'] = str( rich_text(request.event.settings.frontpage_text, safelinks=False)) cache_key = ':'.join([ 'widget.py', 'eventlist', request.organizer.slug, request.event.slug if hasattr(request, 'event') else '-', list_type, request.GET.urlencode(), get_language(), ]) cached_data = cache.get(cache_key) if cached_data: return self.response(cached_data) if list_type == "calendar": self._set_month_year() _, ndays = calendar.monthrange(self.year, self.month) data['date'] = date(self.year, self.month, 1) if hasattr(self.request, 'event'): tz = pytz.timezone(self.request.event.settings.timezone) else: tz = pytz.UTC before = datetime(self.year, self.month, 1, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(self.year, self.month, ndays, 0, 0, 0, tzinfo=tz) + timedelta(days=1) ebd = defaultdict(list) if hasattr(self.request, 'event'): add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated('web').filter( event__sales_channels__contains=self.request. sales_channel.identifier), self.request), before, after, ebd, set(), self.request.event, kwargs.get('cart_namespace')) else: timezones = set() add_events_for_days( self.request, filter_qs_by_attr( Event.annotated( self.request.organizer.events, 'web').filter(sales_channels__contains=self. request.sales_channel.identifier), self.request), before, after, ebd, timezones) add_subevents_for_days( filter_qs_by_attr( SubEvent.annotated( SubEvent.objects.filter( event__organizer=self.request.organizer, event__is_public=True, event__live=True, event__sales_channels__contains=self.request. sales_channel.identifier).prefetch_related( 'event___settings_objects', 'event__organizer___settings_objects')), self.request), before, after, ebd, timezones) data['weeks'] = weeks_for_template(ebd, self.year, self.month) for w in data['weeks']: for d in w: if not d: continue d['events'] = self._serialize_events(d['events'] or []) elif list_type == "week": self._set_week_year() if hasattr(self.request, 'event'): tz = pytz.timezone(self.request.event.settings.timezone) else: tz = pytz.UTC week = isoweek.Week(self.year, self.week) data['week'] = [self.year, self.week] before = datetime(week.monday().year, week.monday().month, week.monday().day, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(week.sunday().year, week.sunday().month, week.sunday().day, 0, 0, 0, tzinfo=tz) + timedelta(days=1) ebd = defaultdict(list) if hasattr(self.request, 'event'): add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated('web'), self.request), before, after, ebd, set(), self.request.event, kwargs.get('cart_namespace')) else: timezones = set() add_events_for_days( self.request, filter_qs_by_attr( Event.annotated(self.request.organizer.events, 'web'), self.request), before, after, ebd, timezones) add_subevents_for_days( filter_qs_by_attr( SubEvent.annotated( SubEvent.objects.filter( event__organizer=self.request.organizer, event__is_public=True, event__live=True, ).prefetch_related( 'event___settings_objects', 'event__organizer___settings_objects')), self.request), before, after, ebd, timezones) data['days'] = days_for_template(ebd, week) for d in data['days']: d['events'] = self._serialize_events(d['events'] or []) else: if hasattr(self.request, 'event'): evs = self.request.event.subevents_sorted( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier), self.request)) tz = pytz.timezone(request.event.settings.timezone) data['events'] = [{ 'name': str(ev.name), 'location': str(ev.location), 'date_range': self._get_date_range(ev, ev.event, tz), 'availability': self._get_availability(ev, ev.event), 'event_url': build_absolute_uri(ev.event, 'presale:event.index'), 'subevent': ev.pk, } for ev in evs] else: data['events'] = [] qs = self._get_event_queryset() for event in qs: tz = pytz.timezone( event.cache.get_or_set( 'timezone', lambda: event.settings.timezone)) if event.has_subevents: dr = daterange(event.min_from.astimezone(tz), (event.max_fromto or event.max_to or event.max_from).astimezone(tz)) avail = { 'color': 'none', 'text': gettext('Event series') } else: dr = self._get_date_range(event, event, tz) avail = self._get_availability(event, event) data['events'].append({ 'name': str(event.name), 'location': str(event.location), 'date_range': dr, 'availability': avail, 'event_url': build_absolute_uri(event, 'presale:event.index'), }) cache.set(cache_key, data, 30) # These pages are cached for a really short duration – this should make them pretty accurate, while still # providing some protection against burst traffic. return self.response(data)
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Show voucher option if an event is selected and vouchers exist vouchers_exist = self.request.event.cache.get('vouchers_exist') if vouchers_exist is None: vouchers_exist = self.request.event.vouchers.exists() self.request.event.cache.set('vouchers_exist', vouchers_exist) if not self.request.event.has_subevents or self.subevent: # Fetch all items items, display_add_to_cart = get_grouped_items( self.request.event, self.subevent, filter_items=self.request.GET.getlist('item'), filter_categories=self.request.GET.getlist('category'), channel=self.request.sales_channel.identifier) context['itemnum'] = len(items) context['allfree'] = all( item.display_price.gross == Decimal('0.00') for item in items if not item.has_variations) and all( all(var.display_price.gross == Decimal('0.00') for var in item.available_variations) for item in items if item.has_variations) # Regroup those by category context['items_by_category'] = item_group_by_category(items) context['display_add_to_cart'] = display_add_to_cart context['show_vouchers'] = vouchers_exist context['vouchers_exist'] = vouchers_exist else: context['show_vouchers'] = False context['vouchers_exist'] = vouchers_exist context['ev'] = self.subevent or self.request.event context['subevent'] = self.subevent context['cart'] = self.get_cart() context['has_addon_choices'] = get_cart( self.request).filter(item__addons__isnull=False).exists() if self.subevent: context['frontpage_text'] = str(self.subevent.frontpage_text) else: context['frontpage_text'] = str( self.request.event.settings.frontpage_text) context['list_type'] = self.request.GET.get( "style", self.request.event.settings.event_list_type) if context['list_type'] not in ( "calendar", "week") and self.request.event.subevents.count() > 100: if self.request.event.settings.event_list_type not in ("calendar", "week"): self.request.event.settings.event_list_type = "calendar" context['list_type'] = "calendar" if context[ 'list_type'] == "calendar" and self.request.event.has_subevents: self._set_month_year() tz = pytz.timezone(self.request.event.settings.timezone) _, ndays = calendar.monthrange(self.year, self.month) before = datetime(self.year, self.month, 1, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(self.year, self.month, ndays, 0, 0, 0, tzinfo=tz) + timedelta(days=1) context['date'] = date(self.year, self.month, 1) context['before'] = before context['after'] = after ebd = defaultdict(list) add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request), before, after, ebd, set(), self.request.event, kwargs.get('cart_namespace')) context['show_names'] = ebd.get( '_subevents_different_names', False) or sum( len(i) for i in ebd.values() if isinstance(i, list)) < 2 context['weeks'] = weeks_for_template(ebd, self.year, self.month) context['months'] = [date(self.year, i + 1, 1) for i in range(12)] context['years'] = range(now().year - 2, now().year + 3) elif context[ 'list_type'] == "week" and self.request.event.has_subevents: self._set_week_year() tz = pytz.timezone(self.request.event.settings.timezone) week = isoweek.Week(self.year, self.week) before = datetime(week.monday().year, week.monday().month, week.monday().day, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(week.sunday().year, week.sunday().month, week.sunday().day, 0, 0, 0, tzinfo=tz) + timedelta(days=1) context['date'] = week.monday() context['before'] = before context['after'] = after ebd = defaultdict(list) add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request), before, after, ebd, set(), self.request.event, kwargs.get('cart_namespace')) context['show_names'] = ebd.get( '_subevents_different_names', False) or sum( len(i) for i in ebd.values() if isinstance(i, list)) < 2 context['days'] = days_for_template(ebd, week) context['weeks'] = [date(self.year, i + 1, 1) for i in range(12)] context['weeks'] = [i + 1 for i in range(53)] context['years'] = range(now().year - 2, now().year + 3) context['week_format'] = get_format('WEEK_FORMAT') if context['week_format'] == 'WEEK_FORMAT': context['week_format'] = WEEK_FORMAT elif self.request.event.has_subevents: context['subevent_list'] = self.request.event.subevents_sorted( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request)) context['show_cart'] = (context['cart']['positions'] and (self.request.event.has_subevents or self.request.event.presale_is_running)) if self.request.event.settings.redirect_to_checkout_directly: context['cart_redirect'] = eventreverse( self.request.event, 'presale:event.checkout.start', kwargs={'cart_namespace': kwargs.get('cart_namespace') or ''}) if context['cart_redirect'].startswith('https:'): context[ 'cart_redirect'] = '/' + context['cart_redirect'].split( '/', 3)[3] else: context['cart_redirect'] = self.request.path return context
def _get_event_list(self, request, **kwargs): data = {} o = getattr(request, 'event', request.organizer) list_type = self.request.GET.get("style", o.settings.event_list_type) data['list_type'] = list_type if hasattr(self.request, 'event') and data['list_type'] not in ("calendar", "week"): # only allow list-view of more than 50 subevents if ordering is by data as this can be done in the database # ordering by name is currently not supported in database due to I18NField-JSON ordering = self.request.event.settings.get( 'frontpage_subevent_ordering', default='date_ascending', as_type=str) if ordering not in ("date_ascending", "date_descending" ) and self.request.event.subevents.filter( date_from__gt=now()).count() > 50: if self.request.event.settings.event_list_type not in ( "calendar", "week"): self.request.event.settings.event_list_type = "calendar" data['list_type'] = list_type = 'calendar' if hasattr(self.request, 'event'): data['name'] = str(request.event.name) data['frontpage_text'] = str( rich_text(request.event.settings.frontpage_text, safelinks=False)) cache_key = ':'.join([ 'widget.py', 'eventlist', request.organizer.slug, request.event.slug if hasattr(request, 'event') else '-', list_type, request.GET.urlencode(), get_language(), ]) cached_data = cache.get(cache_key) if cached_data: return self.response(cached_data) if list_type == "calendar": self._set_month_year() _, ndays = calendar.monthrange(self.year, self.month) data['date'] = date(self.year, self.month, 1) if hasattr(self.request, 'event'): tz = pytz.timezone(self.request.event.settings.timezone) else: tz = pytz.UTC before = datetime(self.year, self.month, 1, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(self.year, self.month, ndays, 0, 0, 0, tzinfo=tz) + timedelta(days=1) ebd = defaultdict(list) if hasattr(self.request, 'event'): add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated('web').filter( event__sales_channels__contains=self.request. sales_channel.identifier), self.request), before, after, ebd, set(), self.request.event, kwargs.get('cart_namespace')) else: timezones = set() add_events_for_days( self.request, filter_qs_by_attr( Event.annotated( self.request.organizer.events, 'web').filter(sales_channels__contains=self. request.sales_channel.identifier), self.request), before, after, ebd, timezones) add_subevents_for_days( filter_qs_by_attr( SubEvent.annotated( SubEvent.objects.filter( event__organizer=self.request.organizer, event__is_public=True, event__live=True, event__sales_channels__contains=self.request. sales_channel.identifier).prefetch_related( 'event___settings_objects', 'event__organizer___settings_objects')), self.request), before, after, ebd, timezones) data['weeks'] = weeks_for_template(ebd, self.year, self.month) for w in data['weeks']: for d in w: if not d: continue d['events'] = self._serialize_events(d['events'] or []) elif list_type == "week": self._set_week_year() if hasattr(self.request, 'event'): tz = pytz.timezone(self.request.event.settings.timezone) else: tz = pytz.UTC week = isoweek.Week(self.year, self.week) data['week'] = [self.year, self.week] before = datetime(week.monday().year, week.monday().month, week.monday().day, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(week.sunday().year, week.sunday().month, week.sunday().day, 0, 0, 0, tzinfo=tz) + timedelta(days=1) ebd = defaultdict(list) if hasattr(self.request, 'event'): add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated('web'), self.request), before, after, ebd, set(), self.request.event, kwargs.get('cart_namespace')) else: timezones = set() add_events_for_days( self.request, filter_qs_by_attr( Event.annotated(self.request.organizer.events, 'web'), self.request), before, after, ebd, timezones) add_subevents_for_days( filter_qs_by_attr( SubEvent.annotated( SubEvent.objects.filter( event__organizer=self.request.organizer, event__is_public=True, event__live=True, ).prefetch_related( 'event___settings_objects', 'event__organizer___settings_objects')), self.request), before, after, ebd, timezones) data['days'] = days_for_template(ebd, week) for d in data['days']: d['events'] = self._serialize_events(d['events'] or []) else: offset = int(self.request.GET.get("offset", 0)) limit = 50 if hasattr(self.request, 'event'): evs = self.request.event.subevents_sorted( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier), self.request)) ordering = self.request.event.settings.get( 'frontpage_subevent_ordering', default='date_ascending', as_type=str) data['has_more_events'] = False if ordering in ("date_ascending", "date_descending"): # fetch one more result than needed to check if more events exist evs = list(evs[offset:offset + limit + 1]) if len(evs) > limit: data['has_more_events'] = True evs = evs[:limit] tz = pytz.timezone(request.event.settings.timezone) if self.request.event.settings.event_list_available_only: evs = [ se for se in evs if not se.presale_has_ended and ( se.best_availability_state is not None and se.best_availability_state >= Quota.AVAILABILITY_RESERVED) ] data['events'] = [{ 'name': str(ev.name), 'location': str(ev.location), 'date_range': self._get_date_range(ev, ev.event, tz), 'availability': self._get_availability(ev, ev.event, tz=tz), 'event_url': build_absolute_uri(ev.event, 'presale:event.index'), 'subevent': ev.pk, } for ev in evs] else: data['events'] = [] qs = self._get_event_queryset() for event in qs: tz = pytz.timezone( event.cache.get_or_set( 'timezone', lambda: event.settings.timezone)) if event.has_subevents: dr = daterange(event.min_from.astimezone(tz), (event.max_fromto or event.max_to or event.max_from).astimezone(tz)) avail = { 'color': 'none', 'text': gettext('Event series') } else: dr = self._get_date_range(event, event, tz) avail = self._get_availability(event, event, tz=tz) data['events'].append({ 'name': str(event.name), 'location': str(event.location), 'date_range': dr, 'availability': avail, 'event_url': build_absolute_uri(event, 'presale:event.index'), }) cache.set(cache_key, data, 30) # These pages are cached for a really short duration – this should make them pretty accurate, while still # providing some protection against burst traffic. return self.response(data)
def _subevent_list_context(self): voucher = None if self.request.GET.get('voucher'): try: voucher = Voucher.objects.get( code__iexact=self.request.GET.get('voucher'), event=self.request.event) except Voucher.DoesNotExist: pass context = {} context['list_type'] = self.request.GET.get( "style", self.request.event.settings.event_list_type) if context['list_type'] not in ( "calendar", "week") and self.request.event.subevents.filter( date_from__gt=now()).count() > 50: if self.request.event.settings.event_list_type not in ("calendar", "week"): self.request.event.settings.event_list_type = "calendar" context['list_type'] = "calendar" if context['list_type'] == "calendar": self._set_month_year() tz = pytz.timezone(self.request.event.settings.timezone) _, ndays = calendar.monthrange(self.year, self.month) before = datetime(self.year, self.month, 1, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(self.year, self.month, ndays, 0, 0, 0, tzinfo=tz) + timedelta(days=1) context['date'] = date(self.year, self.month, 1) context['before'] = before context['after'] = after ebd = defaultdict(list) add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request), before, after, ebd, set(), self.request.event, self.kwargs.get('cart_namespace'), voucher, ) context['show_names'] = ebd.get( '_subevents_different_names', False) or sum( len(i) for i in ebd.values() if isinstance(i, list)) < 2 context['weeks'] = weeks_for_template(ebd, self.year, self.month) context['months'] = [date(self.year, i + 1, 1) for i in range(12)] context['years'] = range(now().year - 2, now().year + 3) elif context['list_type'] == "week": self._set_week_year() tz = pytz.timezone(self.request.event.settings.timezone) week = isoweek.Week(self.year, self.week) before = datetime(week.monday().year, week.monday().month, week.monday().day, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(week.sunday().year, week.sunday().month, week.sunday().day, 0, 0, 0, tzinfo=tz) + timedelta(days=1) context['date'] = week.monday() context['before'] = before context['after'] = after ebd = defaultdict(list) add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request), before, after, ebd, set(), self.request.event, self.kwargs.get('cart_namespace'), voucher, ) context['show_names'] = ebd.get( '_subevents_different_names', False) or sum( len(i) for i in ebd.values() if isinstance(i, list)) < 2 context['days'] = days_for_template(ebd, week) context['weeks'] = [(date_fromisocalendar(self.year, i + 1, 1), date_fromisocalendar(self.year, i + 1, 7)) for i in range(53 if date(self.year, 12, 31). isocalendar()[1] == 53 else 52)] context['years'] = range(now().year - 2, now().year + 3) context['week_format'] = get_format('WEEK_FORMAT') if context['week_format'] == 'WEEK_FORMAT': context['week_format'] = WEEK_FORMAT else: context['subevent_list'] = self.request.event.subevents_sorted( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request)) if self.request.event.settings.event_list_available_only and not voucher: context['subevent_list'] = [ se for se in context['subevent_list'] if not se.presale_has_ended and se.best_availability_state >= Quota.AVAILABILITY_RESERVED ] return context
def _subevent_list_context(self): voucher = None if self.request.GET.get('voucher'): try: voucher = Voucher.objects.get( code__iexact=self.request.GET.get('voucher'), event=self.request.event) except Voucher.DoesNotExist: pass context = {} context['list_type'] = self.request.GET.get( "style", self.request.event.settings.event_list_type) if context['list_type'] not in ( "calendar", "week") and self.request.event.subevents.filter( date_from__gt=now()).count() > 50: if self.request.event.settings.event_list_type not in ("calendar", "week"): self.request.event.settings.event_list_type = "calendar" context['list_type'] = "calendar" if context['list_type'] == "calendar": self._set_month_year() tz = pytz.timezone(self.request.event.settings.timezone) _, ndays = calendar.monthrange(self.year, self.month) before = datetime(self.year, self.month, 1, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(self.year, self.month, ndays, 0, 0, 0, tzinfo=tz) + timedelta(days=1) context['date'] = date(self.year, self.month, 1) context['before'] = before context['after'] = after ebd = defaultdict(list) add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request), before, after, ebd, set(), self.request.event, self.kwargs.get('cart_namespace'), voucher, ) # 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 # in the calendar. We previously only looked at the current time range for this condition which caused weird side-effects, so we need # an extra query to look at the entire series. For performance reasons, we have a limit on how many different names we look at. context['show_names'] = sum( len(i) for i in ebd.values() if isinstance( i, list)) < 2 or self.request.event.cache.get_or_set( 'has_different_subevent_names', lambda: len( set( str(n) for n in self.request.event.subevents.order_by( ).values_list('name', flat=True).annotate( c=Count('*'))[:250])) != 1, timeout=120, ) context['weeks'] = weeks_for_template(ebd, self.year, self.month) context['months'] = [date(self.year, i + 1, 1) for i in range(12)] context['years'] = range(now().year - 2, now().year + 3) elif context['list_type'] == "week": self._set_week_year() tz = pytz.timezone(self.request.event.settings.timezone) week = isoweek.Week(self.year, self.week) before = datetime(week.monday().year, week.monday().month, week.monday().day, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(week.sunday().year, week.sunday().month, week.sunday().day, 0, 0, 0, tzinfo=tz) + timedelta(days=1) context['date'] = week.monday() context['before'] = before context['after'] = after ebd = defaultdict(list) add_subevents_for_days( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request), before, after, ebd, set(), self.request.event, self.kwargs.get('cart_namespace'), voucher, ) # 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 # in the calendar. We previously only looked at the current time range for this condition which caused weird side-effects, so we need # an extra query to look at the entire series. For performance reasons, we have a limit on how many different names we look at. context['show_names'] = sum( len(i) for i in ebd.values() if isinstance( i, list)) < 2 or self.request.event.cache.get_or_set( 'has_different_subevent_names', lambda: len( set( str(n) for n in self.request.event.subevents.order_by( ).values_list('name', flat=True).annotate( c=Count('*'))[:250])) != 1, timeout=120, ) context['days'] = days_for_template(ebd, week) years = (self.year - 1, self.year, self.year + 1) weeks = [] for year in years: weeks += [ (date_fromisocalendar(year, i + 1, 1), date_fromisocalendar(year, i + 1, 7)) for i in range(53 if date(year, 12, 31).isocalendar()[1] == 53 else 52) ] context['weeks'] = [[w for w in weeks if w[0].year == year] for year in years] context['week_format'] = get_format('WEEK_FORMAT') if context['week_format'] == 'WEEK_FORMAT': context['week_format'] = WEEK_FORMAT context['short_month_day_format'] = get_format( 'SHORT_MONTH_DAY_FORMAT') if context['short_month_day_format'] == 'SHORT_MONTH_DAY_FORMAT': context['short_month_day_format'] = SHORT_MONTH_DAY_FORMAT else: context['subevent_list'] = self.request.event.subevents_sorted( filter_qs_by_attr( self.request.event.subevents_annotated( self.request.sales_channel.identifier).using( settings.DATABASE_REPLICA), self.request)) if self.request.event.settings.event_list_available_only and not voucher: context['subevent_list'] = [ se for se in context['subevent_list'] if not se.presale_has_ended and (se.best_availability_state is None or se.best_availability_state >= Quota.AVAILABILITY_RESERVED) ] return context