-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmanagers.py
executable file
·99 lines (87 loc) · 3.67 KB
/
managers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from __future__ import unicode_literals
import datetime
from calendar import monthrange
from django.db import models
from django.db.models import Q
from django.utils.timezone import make_aware, get_default_timezone
class EventManager(models.Manager):
def _get_kwargs(self, category, tag):
"""Helper function for getting category/tag kwargs."""
vals = {
'categories__title__iexact': category,
'tags__name__iexact': tag
}
kwargs = {}
for k, v in vals.items():
if v:
kwargs[k] = v
return kwargs
@staticmethod
def get_first_and_last(year, month):
"""Returns two datetimes: first day and last day of given year&month"""
ym_first = make_aware(
datetime.datetime(year, month, 1),
get_default_timezone()
)
ym_last = make_aware(
datetime.datetime(year, month, monthrange(year, month)[1], 23, 59, 59, 1000000-1),
get_default_timezone()
)
return ym_first, ym_last
def all_month_events(self, year, month, category=None, tag=None,
loc=False, cncl=False):
"""
Returns all events that have an occurrence within the given
month & year.
"""
kwargs = self._get_kwargs(category, tag)
ym_first, ym_last = self.get_first_and_last(year, month)
pref = []
if loc:
pref.append("location")
if cncl:
pref.append("cancellations")
# for yearly repeat, we need to check the start and end date months
# b/c yearly events should occur every year in the same month
r = Q(repeat="YEARLY")
dstart_mo = Q(start_date__month=month)
dend_mo = Q(end_date__month=month)
dstart_yr = Q(start_date__year=year)
dend_yr = Q(end_date__year=year)
return self.model.objects.filter(
# only events that are still repeating
r & (dstart_mo | dend_mo) | # yearly repeat
(~Q(repeat="NEVER")) | # all other repeats
((dstart_yr | dend_yr) & (dstart_mo | dend_yr)), # non-repeating
Q(end_repeat=None) | Q(end_repeat__gte=ym_first),
start_date__lte=ym_last # no events that haven't started yet
).filter(**kwargs).prefetch_related(*pref).order_by('start_date').distinct()
# XXX These are no longer used since all_month_events() (above) was created.
# def month_events(self, year, month, category=None, tag=None):
# """
# Returns the events within the given month and year. If category
# and/or tag is given, the events returned will have
# those categories/tags.
# """
# kwargs = self._get_kwargs(category, tag)
# return self.model.objects.within(year, month).filter(
# **kwargs).prefetch_related('location', 'cancellations')
#
# def within(self, year, month):
# """Returns events within the given year and month."""
# return self.model.objects.filter(
# Q(start_date__year=year) | Q(end_date__year=year),
# Q(start_date__month=month) | Q(end_date__month=month)
# )
def live(self, now):
"""
Returns a queryset of events that will occur again after 'now'.
Used to help generate a list of upcoming events.
"""
return self.model.objects.filter(
Q(end_repeat=None) | Q(end_repeat__gte=now) |
Q(start_date__gte=now) | Q(end_date__gte=now)
).exclude( # exclude single day events that won't occur again
start_date__lt=now, end_date__lt=now,
repeat="NEVER", end_repeat=None,
).prefetch_related('cancellations')