Skip to content

Instantly share code, notes, and snippets.

@cnk
Created July 10, 2024 20:58
Show Gist options
  • Save cnk/603c48f6029e033d38e006db6988843a to your computer and use it in GitHub Desktop.
Save cnk/603c48f6029e033d38e006db6988843a to your computer and use it in GitHub Desktop.
Calendar views
class MasterCalendarPage(RoutablePageMixin, Page):
## Fields - including one that sets the default time period: day, week, month
## Helpers
def _build_date_filtered_queryset(self, site, start_date, end_date):
queryset = self.base_queryset(site)
if start_date:
# If the user selected a start date, exclude all events that ended before then.
queryset = queryset.exclude(end_date__lte=start_date)
if end_date:
# If the user selected an end date, exclude all events that started a day afterward.
# This way, searching for Mar 19 - Mar 20 gets you the events on both the 19th and the 20th.
queryset = queryset.exclude(start_date__gte=end_date + timedelta(days=1))
return queryset
def _date_in_allowed_range(self, dt):
"""
Robots will just keep itterating on dates so we need to limit them to relevant date ranges
"""
return dt.date() >= settings.CALENDAR_START_DATE and dt.date() <= date.today() + settings.CALENDAR_END_DELTA
def _get_week_range(self, specified_date=None):
if not specified_date:
# If not specified_date was provided, use the datetime object that represents today.
specified_date = localtime().replace(hour=0, minute=0, second=0, microsecond=0)
# The %w format gives the weekday number (Sunday being 0).
num_days_since_sunday = int(specified_date.strftime('%w'))
start_date = specified_date - timedelta(days=num_days_since_sunday)
end_date = start_date + timedelta(days=7)
return start_date, end_date
def _get_month_range(self, month_string=None):
if month_string:
# Because of DATE_PARSER_SETTINGS, providing '2017-12' here gets us the datetime for 2017-12-01.
start_date = parse(month_string, settings=DATE_PARSER_SETTINGS)
else:
# Start with midnight today, then replace the day-of-the-month with 1 to get the first day of this month.
start_date = parse('midnight today', settings=DATE_PARSER_SETTINGS).replace(day=1)
end_date = start_date + relativedelta(months=1)
return start_date, end_date
## Views
@path('')
def default_view(self, request):
if self.default_time_period == 'day':
start_date = localtime().replace(hour=0, minute=0, second=0, microsecond=0)
end_date = start_date + timedelta(days=1)
elif self.default_time_period == 'week':
# Get the date range for the current week.
start_date, end_date = self._get_week_range()
elif self.default_time_period == 'month':
# Get the date range for the current month.
start_date, end_date = self._get_month_range()
else: # self.default_time_period == 'future':
start_date = localtime()
end_date = None
context['events'] = self._build_date_filtered_queryset(site, start_date, end_date)
return self.render(request, context_overrides=context)
@path('day/', name='day')
@re_path(r'^day/(\d{4}-\d{1,2}-\d{1,2})/$', name='day')
def day_view(self, request, date_string=None):
"""
Displays all Events from a single, specified day, provided via a string like '2017-12-10'.
"""
if date_string:
start_date = parse(date_string, settings=DATE_PARSER_SETTINGS)
else:
start_date = localtime().replace(hour=0, minute=0, second=0, microsecond=0)
end_date = start_date + timedelta(days=1)
# Do not render this page if the user requested a day outside of the Calendar start and end range.
if not self._date_in_allowed_range(start_date):
raise Http404()
context['events'] = self._build_date_filtered_queryset(site, start_date, end_date)
return self.render(request, context_overrides=context)
@path('week/', name='week')
@re_path(r'^week/(\d{4}-\d{1,2}-\d{1,2})/$', name='week')
def week_view(self, request, date_string=None):
"""
Displays all Events from a single week.
Any date provided via a string like '2017-12-10' will display the week during which that date occurs, starting
on Sunday and ending on Saturday.
If no date is provided or the date_string isn't valid, the current week is displayed.
"""
specified_date = parse(date_string or 'midnight today', settings=DATE_PARSER_SETTINGS)
start_date, end_date = self._get_week_range(specified_date)
# Do not render this page if the user requested a day outside of the Calendar start and end range.
if not self._date_in_allowed_range(start_date):
raise Http404()
context['events'] = self._build_date_filtered_queryset(site, start_date, end_date)
return self.render(request, context_overrides=context)
@path('month/', name='month')
@re_path(r'^month/(\d{4}-\d{1,2})/$', name='month')
def month_view(self, request, month_string=None):
"""
Displays all Events in a single month.
Any month provided via a string like '2017-12' will display that month.
If no month is provided or the month is invalid, the current month is displayed.
"""
start_date, end_date = self._get_month_range(month_string)
# Do not render this page if the user requested a day outside of the Calendar start and end range.
if not self._date_in_allowed_range(start_date):
raise Http404()
context['events'] = self._build_date_filtered_queryset(site, start_date, end_date)
return self.render(request, context_overrides=context)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment