Test coverage report: calendarium.views

# calendarium.views: 197 total statements, 96.7% covered

Generated: Thu 2013-05-02 12:21 SGT

Source file: /Users/martin/Repos/django-calendarium/calendarium/views.py

Stats: 178 executed, 6 missed, 13 excluded, 104 ignored

1. `"""Views for the ``calendarium`` app."""`
2. `import calendar`
3. `from dateutil.relativedelta import relativedelta`
4. ``
5. `from django.contrib.auth.decorators import permission_required`
6. `from django.core.urlresolvers import reverse`
7. `from django.forms.models import model_to_dict`
8. `from django.http import Http404, HttpResponseRedirect`
9. `from django.utils.decorators import method_decorator`
10. `from django.utils.timezone import datetime, now, timedelta, utc`
11. `from django.views.generic import (`
12. `CreateView,`
13. `DeleteView,`
14. `DetailView,`
15. `RedirectView,`
16. `TemplateView,`
17. `UpdateView,`
18. `)`
19. ``
20. `from .constants import OCCURRENCE_DECISIONS`
21. `from .forms import OccurrenceForm`
22. `from .models import EventCategory, Event, Occurrence`
23. `from .utils import monday_of_week`
24. ``
25. ``
26. `class CategoryMixin(object):`
27. `"""Mixin to handle category filtering."""`
28. `def dispatch(self, request, *args, **kwargs):`
29. `if request.GET.get('category'):`
30. `try:`
31. `category_id = int(request.GET.get('category'))`
32. `except ValueError:`
33. `pass`
34. `else:`
35. `try:`
36. `self.category = EventCategory.objects.get(pk=category_id)`
37. `except EventCategory.DoesNotExist:`
38. `pass`
39. `return super(CategoryMixin, self).dispatch(request, *args, **kwargs)`
40. ``
41. `def get_category_context(self, **kwargs):`
42. `context = {'categories': EventCategory.objects.all()}`
43. `if hasattr(self, 'category'):`
44. `context.update({'current_category': self.category})`
45. `return context`
46. ``
47. ``
48. `class CalendariumRedirectView(RedirectView):`
49. `"""View to redirect to the current month view."""`
50. `def get_redirect_url(self, **kwargs):`
51. `return reverse('calendar_month', kwargs={'year': now().year,`
52. `'month': now().month})`
53. ``
54. ``
55. `class MonthView(CategoryMixin, TemplateView):`
56. `"""View to return all occurrences of an event for a whole month."""`
57. `template_name = 'calendarium/calendar_month.html'`
58. ``
59. `def dispatch(self, request, *args, **kwargs):`
60. `self.month = int(kwargs.get('month'))`
61. `self.year = int(kwargs.get('year'))`
62. `if self.month not in range(1, 13):`
63. `raise Http404`
64. `if request.method == 'POST':`
65. `if request.POST.get('next'):`
66. `new_date = datetime(self.year, self.month, 1) + timedelta(`
67. `days=31)`
68. `return HttpResponseRedirect(reverse('calendar_month', kwargs={`
69. `'year': new_date.year, 'month': new_date.month}))`
70. `elif request.POST.get('previous'):`
71. `new_date = datetime(self.year, self.month, 1) - timedelta(`
72. `days=1)`
73. `return HttpResponseRedirect(reverse('calendar_month', kwargs={`
74. `'year': new_date.year, 'month': new_date.month}))`
75. `elif request.POST.get('today'):`
76. `return HttpResponseRedirect(reverse('calendar_month', kwargs={`
77. `'year': now().year, 'month': now().month}))`
78. `if request.is_ajax():`
79. `self.template_name = 'calendarium/partials/calendar_month.html'`
80. `return super(MonthView, self).dispatch(request, *args, **kwargs)`
81. ``
82. `def get_context_data(self, **kwargs):`
83. `ctx = self.get_category_context()`
84. `month = [[]]`
85. `week = 0`
86. `start = datetime(year=self.year, month=self.month, day=1, tzinfo=utc)`
87. `end = datetime(`
88. `year=self.year, month=self.month, day=1, tzinfo=utc`
89. `) + relativedelta(months=1)`
90. ``
91. `all_occurrences = Event.objects.get_occurrences(`
92. `start, end, ctx.get('current_category'))`
93. `for day in calendar.Calendar().itermonthdays(self.year, self.month):`
94. `current = False`
95. `if day:`
96. `date = datetime(year=self.year, month=self.month, day=day,`
97. `tzinfo=utc)`
98. `occurrences = filter(`
99. `lambda occ, date=date: occ.start.replace(`
100. `hour=0, minute=0, second=0, microsecond=0) == date,`
101. `all_occurrences)`
102. `if date.date() == now().date():`
103. `current = True`
104. `else:`
105. `occurrences = []`
106. `month[week].append((day, occurrences, current))`
107. `if len(month[week]) == 7:`
108. `month.append([])`
109. `week += 1`
110. `ctx.update({'month': month, 'date': date})`
111. `return ctx`
112. ``
113. ``
114. `class WeekView(CategoryMixin, TemplateView):`
115. `"""View to return all occurrences of an event for one week."""`
116. `template_name = 'calendarium/calendar_week.html'`
117. ``
118. `def dispatch(self, request, *args, **kwargs):`
119. `self.week = int(kwargs.get('week'))`
120. `self.year = int(kwargs.get('year'))`
121. `if self.week not in range(1, 53):`
122. `raise Http404`
123. `if request.method == 'POST':`
124. `if request.POST.get('next'):`
125. `date = monday_of_week(self.year, self.week) + timedelta(days=7)`
126. `return HttpResponseRedirect(reverse('calendar_week', kwargs={`
127. `'year': date.year, 'week': date.date().isocalendar()[1]}))`
128. `elif request.POST.get('previous'):`
129. `date = monday_of_week(self.year, self.week) - timedelta(days=7)`
130. `return HttpResponseRedirect(reverse('calendar_week', kwargs={`
131. `'year': date.year, 'week': date.date().isocalendar()[1]}))`
132. `elif request.POST.get('today'):`
133. `return HttpResponseRedirect(reverse('calendar_week', kwargs={`
134. `'year': now().year,`
135. `'week': now().date().isocalendar()[1]}))`
136. `if request.is_ajax():`
137. `self.template_name = 'calendarium/partials/calendar_week.html'`
138. `return super(WeekView, self).dispatch(request, *args, **kwargs)`
139. ``
140. `def get_context_data(self, **kwargs):`
141. `ctx = self.get_category_context()`
142. `date = monday_of_week(self.year, self.week)`
143. `week = []`
144. `day = 0`
145. `start = date`
146. `end = date + relativedelta(days=7)`
147. `all_occurrences = Event.objects.get_occurrences(`
148. `start, end, ctx.get('current_category'))`
149. `while day < 7:`
150. `current = False`
151. `occurrences = filter(`
152. `lambda occ, date=date: occ.start.replace(`
153. `hour=0, minute=0, second=0, microsecond=0) == date,`
154. `all_occurrences)`
155. `if date.date() == now().date():`
156. `current = True`
157. `week.append((date, occurrences, current))`
158. `day += 1`
159. `date = date + timedelta(days=1)`
160. `ctx.update({'week': week, 'date': date, 'week_nr': self.week})`
161. `return ctx`
162. ``
163. ``
164. `class DayView(CategoryMixin, TemplateView):`
165. `"""View to return all occurrences of an event for one day."""`
166. `template_name = 'calendarium/calendar_day.html'`
167. ``
168. `def dispatch(self, request, *args, **kwargs):`
169. `self.day = int(kwargs.get('day'))`
170. `self.month = int(kwargs.get('month'))`
171. `self.year = int(kwargs.get('year'))`
172. `try:`
173. `self.date = datetime(year=self.year, month=self.month,`
174. `day=self.day, tzinfo=utc)`
175. `except ValueError:`
176. `raise Http404`
177. `if request.method == 'POST':`
178. `if request.POST.get('next'):`
179. `date = self.date + timedelta(days=1)`
180. `return HttpResponseRedirect(reverse('calendar_day', kwargs={`
181. `'year': date.year, 'month': date.month, 'day': date.day}))`
182. `elif request.POST.get('previous'):`
183. `date = self.date - timedelta(days=1)`
184. `return HttpResponseRedirect(reverse('calendar_day', kwargs={`
185. `'year': date.year, 'month': date.month, 'day': date.day}))`
186. `elif request.POST.get('today'):`
187. `return HttpResponseRedirect(reverse('calendar_day', kwargs={`
188. `'year': now().year, 'month': now().month,`
189. `'day': now().day}))`
190. `if request.is_ajax():`
191. `self.template_name = 'calendarium/partials/calendar_day.html'`
192. `return super(DayView, self).dispatch(request, *args, **kwargs)`
193. ``
194. `def get_context_data(self, **kwargs):`
195. `ctx = self.get_category_context()`
196. `occurrences = Event.objects.get_occurrences(`
197. `self.date, self.date, ctx.get('current_category'))`
198. `ctx.update({'date': self.date, 'occurrences': occurrences})`
199. `return ctx`
200. ``
201. ``
202. `class EventDetailView(DetailView):`
203. `"""View to return information of an event."""`
204. `model = Event`
205. ``
206. ``
207. `class EventMixin(object):`
208. `"""Mixin to handle event-related functions."""`
209. `model = Event`
210. ``
211. `@method_decorator(permission_required('calendarium.add_event'))`
212. `def dispatch(self, request, *args, **kwargs):`
213. `return super(EventMixin, self).dispatch(request, *args, **kwargs)`
214. ``
215. ``
216. `class EventUpdateView(EventMixin, UpdateView):`
217. `"""View to update information of an event."""`
218. `pass`
219. ``
220. ``
221. `class EventCreateView(EventMixin, CreateView):`
222. `"""View to create an event."""`
223. `pass`
224. ``
225. ``
226. `class EventDeleteView(EventMixin, DeleteView):`
227. `"""View to delete an event."""`
228. `pass`
229. ``
230. ``
231. `class OccurrenceViewMixin(object):`
232. `"""Mixin to avoid repeating code for the Occurrence view classes."""`
233. `form_class = OccurrenceForm`
234. ``
235. `def dispatch(self, request, *args, **kwargs):`
236. `try:`
237. `self.event = Event.objects.get(pk=kwargs.get('pk'))`
238. `except Event.DoesNotExist:`
239. `raise Http404`
240. `year = int(kwargs.get('year'))`
241. `month = int(kwargs.get('month'))`
242. `day = int(kwargs.get('day'))`
243. `try:`
244. `date = datetime(year, month, day, tzinfo=utc)`
245. `except TypeError:`
246. `raise Http404`
247. `# this should retrieve the one single occurrence, that has a`
248. `# matching start date`
249. `try:`
250. `occ = Occurrence.objects.get(`
251. `start__year=year, start__month=month, start__day=day)`
252. `except Occurrence.DoesNotExist:`
253. `occ_gen = self.event.get_occurrences(self.event.start)`
254. `occ = occ_gen.next()`
255. `while occ.start.date() < date.date():`
256. `occ = occ_gen.next()`
257. `if occ.start.date() == date.date():`
258. `self.occurrence = occ`
259. `else:`
260. `raise Http404`
261. `self.object = self.occurrence`
262. `return super(OccurrenceViewMixin, self).dispatch(`
263. `request, *args, **kwargs)`
264. ``
265. `def get_object(self):`
266. `return self.occurrence`
267. ``
268. `def get_form_kwargs(self):`
269. `kwargs = super(OccurrenceViewMixin, self).get_form_kwargs()`
270. `kwargs.update({'initial': model_to_dict(self.occurrence)})`
271. `return kwargs`
272. ``
273. ``
274. `class OccurrenceDeleteView(OccurrenceViewMixin, DeleteView):`
275. `"""View to delete an occurrence of an event."""`
276. `def delete(self, request, *args, **kwargs):`
277. `self.object = self.get_object()`
278. `decision = self.request.POST.get('decision')`
279. `self.object.delete_period(decision)`
280. `return HttpResponseRedirect(self.get_success_url())`
281. ``
282. `def get_context_data(self, object):`
283. `ctx = super(OccurrenceDeleteView, self).get_context_data()`
284. `ctx.update({`
285. `'decisions': OCCURRENCE_DECISIONS,`
286. `'object': self.object`
287. `})`
288. `return ctx`
289. ``
290. `def get_success_url(self):`
291. `return reverse('calendar_current_month')`
292. ``
293. ``
294. `class OccurrenceDetailView(OccurrenceViewMixin, DetailView):`
295. `"""View to show information of an occurrence of an event."""`
296. `pass`
297. ``
298. ``
299. `class OccurrenceUpdateView(OccurrenceViewMixin, UpdateView):`
300. `"""View to edit an occurrence of an event."""`
301. `pass`