diff --git a/schedule/views.py b/schedule/views.py index cef39c55..409b556f 100644 --- a/schedule/views.py +++ b/schedule/views.py @@ -327,20 +327,22 @@ def get_next_url(request, default): @check_calendar_permissions def api_occurrences(request): - start = request.GET.get("start") - end = request.GET.get("end") - calendar_slug = request.GET.get("calendar_slug") - timezone = request.GET.get("timezone") + start = request.GET.get('start') + end = request.GET.get('end') + timezone = request.GET.get('timezone') + + calendar_slugs_raw = request.GET.get('calendar_slug') + calendar_slugs = calendar_slugs_raw.split(',') if calendar_slugs_raw else [] try: - response_data = _api_occurrences(start, end, calendar_slug, timezone) + response_data = _api_occurrences(start, end, calendar_slugs, timezone) except (ValueError, Calendar.DoesNotExist) as e: return HttpResponseBadRequest(e) return JsonResponse(response_data, safe=False) -def _api_occurrences(start, end, calendar_slug, timezone): +def _api_occurrences(start, end, calendar_slugs, timezone): if not start or not end: raise ValueError("Start and end parameters are required") @@ -376,9 +378,14 @@ def convert(ddatetime): start = utc.localize(start) end = utc.localize(end) - if calendar_slug: + if calendar_slugs: # will raise DoesNotExist exception if no match - calendars = [Calendar.objects.get(slug=calendar_slug)] + calendars = list(Calendar.objects.filter(slug__in=calendar_slugs)) + missing_calendars = set(calendar_slugs) - set([s.slug for s in calendars]) + if missing_calendars: + missing_msg = ", ".join("'{0}'".format(s) for s in missing_calendars) + msg = "Calendars {0} do not exist.".format(missing_msg) + raise Calendar.DoesNotExist(msg) # if no calendar slug is given, get all the calendars else: calendars = Calendar.objects.all() diff --git a/tests/test_views.py b/tests/test_views.py index 7254141f..f74b7818 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -580,6 +580,69 @@ def test_occurrences_api_fails_with_incorrect_date_string_formats(self): expected_error = "does not match format '%Y-%m-%dT%H:%M:%S'" self.assertIn(expected_error, resp) + def test_cal_multiple_slugs_return_all_events(self): + calendar1 = Calendar.objects.create(name="MyCal1", slug='MyCalSlug1') + calendar2 = Calendar.objects.create(name="MyCal2", slug='MyCalSlug2') + calendarOther = Calendar.objects.create(name="MyCalOther", slug='MyCalSlugOther') + + event1 = Event.objects.create( + title='Recent Event 1', + start=datetime.datetime(2008, 1, 5, 8, 0, tzinfo=pytz.utc), + end=datetime.datetime(2008, 1, 5, 9, 0, tzinfo=pytz.utc), + end_recurring_period=datetime.datetime(2008, 5, 5, 0, 0, tzinfo=pytz.utc), + calendar=calendar1, + ) + event2 = Event.objects.create( + title='Recent Event 2', + start=datetime.datetime(2008, 1, 5, 8, 0, tzinfo=pytz.utc), + end=datetime.datetime(2008, 1, 5, 9, 0, tzinfo=pytz.utc), + end_recurring_period=datetime.datetime(2008, 5, 5, 0, 0, tzinfo=pytz.utc), + calendar=calendar2, + ) + + eventOther = Event.objects.create( + title='Recent Event Other', + start=datetime.datetime(2008, 1, 5, 8, 0, tzinfo=pytz.utc), + end=datetime.datetime(2008, 1, 5, 9, 0, tzinfo=pytz.utc), + end_recurring_period=datetime.datetime(2008, 5, 5, 0, 0, tzinfo=pytz.utc), + calendar=calendarOther, + ) + + calendar_slug = ','.join(['MyCalSlug1', 'MyCalSlug2', ]) + + # Test both present with no cal arg + response = self.client.get(reverse("api_occurrences"), + {'start': '2008-01-05', + 'end': '2008-02-05', + 'calendar_slug': calendar_slug, } + ) + self.assertEqual(response.status_code, 200) + resp_list = json.loads(response.content.decode('utf-8')) + self.assertIn(event1.title, [d['title'] for d in resp_list]) + self.assertIn(event2.title, [d['title'] for d in resp_list]) + + self.assertNotIn(eventOther.title, [d['title'] for d in resp_list]) + + def test_cal_request_missing_returns_400(self): + calendar1 = Calendar.objects.create(name="MyCal1", slug='MyCalSlug1') + + Event.objects.create( + title='Recent Event 1', + start=datetime.datetime(2008, 1, 5, 8, 0, tzinfo=pytz.utc), + end=datetime.datetime(2008, 1, 5, 9, 0, tzinfo=pytz.utc), + end_recurring_period=datetime.datetime(2008, 5, 5, 0, 0, tzinfo=pytz.utc), + calendar=calendar1, + ) + + calendar_slug = ','.join(['MyCalSlug1', 'MyCalSlugOther', ]) + # Test both present with no cal arg + response = self.client.get(reverse("api_occurrences"), + {'start': '2008-01-05', + 'end': '2008-02-05', + 'calendar_slug': calendar_slug, } + ) + self.assertContains(response, 'MyCalSlugOther', status_code=400) + def test_check_next_url_valid_case(self): expected = "/calendar/1" res = check_next_url("/calendar/1")