Repository: carpentries/amy

Issue:
Add event organizer info to the API
Compute Canada would like to be able to use the API to pull all the events it is hosting and then use this information to populate website.

Might be nice to have the EventBrite IDs there too.



Discussion:

Resolving patch:
diff --git a/api/serializers.py b/api/serializers.py
--- a/api/serializers.py
+++ b/api/serializers.py
@@ -35,6 +35,7 @@ class EventSerializer(serializers.ModelSerializer):
     start = serializers.DateField(format=None)
     end = serializers.DateField(format=None)
     url = serializers.URLField(source='website_url')
+    eventbrite_id = serializers.CharField(source='reg_key')
 
     def get_humandate(self, obj):
         """Render start and end dates as human-readable short date."""
@@ -62,5 +63,5 @@ class Meta:
         model = Event
         fields = (
             'slug', 'start', 'end', 'url', 'humandate', 'contact', 'country',
-            'venue', 'address', 'latitude', 'longitude',
+            'venue', 'address', 'latitude', 'longitude', 'eventbrite_id',
         )
diff --git a/api/views.py b/api/views.py
--- a/api/views.py
+++ b/api/views.py
@@ -1,5 +1,6 @@
 from django.db.models import Q
 from rest_framework.generics import ListAPIView
+from rest_framework.metadata import SimpleMetadata
 from rest_framework.permissions import IsAuthenticatedOrReadOnly
 from rest_framework.response import Response
 from rest_framework.reverse import reverse
@@ -14,6 +15,21 @@
 )
 
 
+class QueryMetadata(SimpleMetadata):
+    """Additionally include info about query parameters."""
+
+    def determine_metadata(self, request, view):
+        print('doing something')
+        data = super().determine_metadata(request, view)
+
+        try:
+            data['query_params'] = view.get_query_params_description()
+        except AttributeError:
+            pass
+
+        return data
+
+
 class ApiRoot(APIView):
     def get(self, request, format=None):
         return Response({
@@ -46,9 +62,34 @@ class ExportInstructorLocationsView(ListAPIView):
 
 
 class PublishedEvents(ListAPIView):
+    """List published events."""
+
     # only events that have both a starting date and a URL
     permission_classes = (IsAuthenticatedOrReadOnly, )
     paginator = None  # disable pagination
 
     serializer_class = EventSerializer
-    queryset = Event.objects.published_events()
+
+    metadata_class = QueryMetadata
+
+    def get_queryset(self):
+        """Optionally restrict the returned event set to events hosted by
+        specific host or administered by specific admin."""
+        queryset = Event.objects.published_events()
+
+        administrator = self.request.query_params.get('administrator', None)
+        if administrator is not None:
+            queryset = queryset.filter(administrator__pk=administrator)
+
+        host = self.request.query_params.get('host', None)
+        if host is not None:
+            queryset = queryset.filter(host__pk=host)
+
+        return queryset
+
+    def get_query_params_description(self):
+        return {
+            'administrator': 'ID of the organization responsible for admin '
+                             'work on events.',
+            'host': 'ID of the organization hosting the event.',
+        }


Test patch:
diff --git a/api/test/test_events.py b/api/test/test_events.py
--- a/api/test/test_events.py
+++ b/api/test/test_events.py
@@ -1,5 +1,6 @@
 import datetime
 import json
+from unittest.mock import patch
 
 from django.core.urlresolvers import reverse
 from rest_framework import status
@@ -50,6 +51,7 @@ def setUp(self):
             host=host, latitude=3, longitude=-2, venue='University',
             address='On the street', country='US', contact='sb@sth.edu',
             url='http://github.com/user/repository/',
+            reg_key='12341234',
         )
         # event with missing start
         self.event4 = Event.objects.create(
@@ -84,6 +86,7 @@ def setUp(self):
                 'country': 'US',
                 'url': 'https://user.github.io/repository/',
                 'contact': 'sb@sth.edu',
+                'eventbrite_id': '12341234',
             },
             {
                 'slug': 'event2',
@@ -99,6 +102,7 @@ def setUp(self):
                 'country': 'US',
                 'url': 'https://user.github.io/repository/',
                 'contact': 'sb@sth.edu',
+                'eventbrite_id': None,
             },
             {
                 'slug': 'event1',
@@ -112,10 +116,14 @@ def setUp(self):
                 'country': 'US',
                 'url': 'https://user.github.io/repository/',
                 'contact': 'sb@sth.edu',
+                'eventbrite_id': None,
             },
         ]
 
-    def test_serialization(self):
+    @patch.object(PublishedEvents, 'request', query_params={}, create=True)
+    def test_serialization(self, mock_request):
+        # we're mocking a request here because it's not possible to create
+        # a fake request context for the view
         response = self.serializer_class(self.view().get_queryset(), many=True)
         self.assertEqual(response.data, self.expecting)