views.py 10.7 KB
Newer Older
1
"""
2
3
api/views.py

4
5
Rest Framework Class Views
"""
6
7
8
9
# Future Imports
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

10
11
12
# Python std. lib. imports
import datetime

13
# App Imports
David Haynes's avatar
David Haynes committed
14
from .models import Facility, OpenTime, Category, Schedule, Location, Alert
15
from .serializers import (CategorySerializer, FacilitySerializer,
David Haynes's avatar
David Haynes committed
16
                          ScheduleSerializer, OpenTimeSerializer,
David Haynes's avatar
David Haynes committed
17
                          LocationSerializer, AlertSerializer)
18

19
# Other Imports
David Haynes's avatar
David Haynes committed
20
21
from rest_framework import viewsets, filters
from django_filters.rest_framework import DjangoFilterBackend
22

David Haynes's avatar
David Haynes committed
23
24
class AlertViewSet(viewsets.ReadOnlyModelViewSet):
    """
25
26
27
28
29
30
31
32
33
34
35
    Some type of notification that is displayed to clients that conveys a message.

    Past examples include:
        - random closings
        - modified schedules being in effect
        - election reminder
        - advertising for other SRCT projects

    Alerts last for a period of time until the information is no longer dank.

    GET /api/alerts/
David Haynes's avatar
David Haynes committed
36
    Return all Alert objects.
37
38
39
40
41
42
43
44
45
46
47
48
49
50

    Built-in query parameters:

    GET /api/alerts/?search=
    Query parameter that returns objects that match a keyword provided in the search.

    GET /api/alerts/?ordering=
    Query parameter that orders the returned objects based on the provided field to order by.

    Additionally, you can query against any field you like:

    ie.
    GET /api/alerts/?urgency_tag=major
    will return the Alert objects that are tagged as "major" urgency.
David Haynes's avatar
David Haynes committed
51
    """
52
53
54
55
56
57
58
59
60
61
    # All model fields that are available for filtering
    FILTER_FIELDS = (
        # Alert fields
        'urgency_tag',
        'message',
        'start_datetime',
        'end_datetime'
    )

    # Associate a serializer with the ViewSet
David Haynes's avatar
David Haynes committed
62
63
    serializer_class = AlertSerializer

64
65
66
67
68
69
70
    # Setup filtering
    filter_backends = (filters.SearchFilter, DjangoFilterBackend,
                       filters.OrderingFilter, )
    search_fields = FILTER_FIELDS
    ordering_fields = FILTER_FIELDS
    filter_fields = FILTER_FIELDS

David Haynes's avatar
David Haynes committed
71
    def get_queryset(self):
72
73
74
75
        """
        Handle incoming GET requests and enumerate objects that get returned by
        the API.
        """
David Haynes's avatar
David Haynes committed
76
77
        return Alert.objects.all()

78
class CategoryViewSet(viewsets.ReadOnlyModelViewSet):
79
    """
80
81
82
83
84
85
86
87
    A Category is a grouping of Facilities that serve a common/similar purpose.

    ex.
        - Dining
        - Gyms
        - Study areas (Libraries, The Ridge, JC, etc)

    GET /api/categories/
David Haynes's avatar
David Haynes committed
88
    Return all Category objects.
89
90
91
92
93
94
95
96
97
98
99
100
101
102

    Built-in query parameters:

    GET /api/categories/?search=
    Query parameter that returns objects that match a keyword provided in the search.

    GET /api/categories/?ordering=
    Query parameter that orders the returned objects based on the provided field to order by.

    Additionally, you can query against any field you like:

    ie.
    GET /api/categories/?name=dining
    will return the Category object that is named "dining".
103
    """
104
105
106
107
108
109
110
    # All model fields that are available for filtering
    FILTER_FIELDS = (
        # Category fields
        'name',
    )

    # Associate a serializer with the ViewSet
111
112
    serializer_class = CategorySerializer

113
114
115
116
117
118
119
    # Setup filtering
    filter_backends = (filters.SearchFilter, DjangoFilterBackend,
                       filters.OrderingFilter, )
    search_fields = FILTER_FIELDS
    ordering_fields = FILTER_FIELDS
    filter_fields = FILTER_FIELDS

David Haynes's avatar
David Haynes committed
120
    def get_queryset(self):
121
122
123
124
        """
        Handle incoming GET requests and enumerate objects that get returned by
        the API.
        """
David Haynes's avatar
David Haynes committed
125
126
        return Category.objects.all()

David Haynes's avatar
David Haynes committed
127
128
class LocationViewSet(viewsets.ReadOnlyModelViewSet):
    """
129
130
131
    Represents a specific location that a Facility can be found.

    GET /api/locations/
David Haynes's avatar
David Haynes committed
132
    Return all Location objects.
133
134
135
136
137
138
139
140
141
142
143
144
145
146

    Built-in query parameters:

    GET /api/locations/?search=
    Query parameter that returns objects that match a keyword provided in the search.

    GET /api/locations/?ordering=
    Query parameter that orders the returned objects based on the provided field to order by.

    Additionally, you can query against any field you like:

    ie.
    GET /api/locations/?building=Johnson+Center
    will return all Location objects located in the "Johnson Center" building.
David Haynes's avatar
David Haynes committed
147
    """
148
149
150
151
152
153
154
155
156
    # All model fields that are available for filtering
    FILTER_FIELDS = (
        # Location fields
        'building',
        'address',
        'on_campus'
    )

    # Associate a serializer with the ViewSet
David Haynes's avatar
David Haynes committed
157
158
    serializer_class = LocationSerializer

159
160
161
162
163
164
165
    # Setup filtering
    filter_backends = (filters.SearchFilter, DjangoFilterBackend,
                       filters.OrderingFilter, )
    search_fields = FILTER_FIELDS
    ordering_fields = FILTER_FIELDS
    filter_fields = FILTER_FIELDS

David Haynes's avatar
David Haynes committed
166
    def get_queryset(self):
167
168
169
170
        """
        Handle incoming GET requests and enumerate objects that get returned by
        the API.
        """
David Haynes's avatar
David Haynes committed
171
172
        return Location.objects.all()

173
class FacilityViewSet(viewsets.ReadOnlyModelViewSet):
174
    """
175
176
177
178
179
    A Facility is some type of establishment that has a schedule of open hours and a location that serves a specific purpose that can be categorized.

    GET /api/facilities/
    Return all Facility objects. We additionally filter out stale special_schedules to reduce client side calculations.

David Haynes's avatar
David Haynes committed
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
    Built-in query parameters:

    GET /api/facilities/?search=
    Query parameter that returns objects that match a keyword provided in the search.

    GET /api/facilities/?ordering=
    Query parameter that orders the returned objects based on the provided field to order by.

    Additionally, you can query against any field you like:

    ie.
    GET /api/facilities/?facility_name=Southside
    will return the Facility object that has "Southside" as its name.

    Custom query parameters:

196
197
    GET /api/facilities/?open_now
    Query parameter that only returns open Facility objects.
David Haynes's avatar
David Haynes committed
198
199
200

    GET /api/facilities/?closed_now
    Query parameter that only returns closed Facility objects.
201
    """
202
    # All model fields that are available for filtering
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    FILTER_FIELDS = (
        # Facility fields
        'facility_name',
        'tapingo_url',
        'facility_product_tags__name',
        # Category fields
        'facility_category__name',
        # Location fields
        'facility_location__building',
        'facility_location__address',
        'facility_location__on_campus',
        # Schedule fields
        'main_schedule__name',
        'main_schedule__valid_start',
        'main_schedule__valid_end',
        'special_schedules__name',
        'special_schedules__valid_start',
        'special_schedules__valid_end',
    )

David Haynes's avatar
David Haynes committed
223
    # Associate a serializer with the ViewSet
224
    serializer_class = FacilitySerializer
225
226

    # Setup filtering
227
228
229
230
231
    filter_backends = (filters.SearchFilter, DjangoFilterBackend,
                       filters.OrderingFilter, )
    search_fields = FILTER_FIELDS
    ordering_fields = FILTER_FIELDS
    filter_fields = FILTER_FIELDS
232

233
    def get_queryset(self):
234
        """
235
236
        Handle incoming GET requests and enumerate objects that get returned by
        the API.
237
        """
David Haynes's avatar
David Haynes committed
238
        # Define ?open_now
David Haynes's avatar
David Haynes committed
239
        open_now = self.request.query_params.get('open_now', None)
David Haynes's avatar
David Haynes committed
240
241
242
        # Define ?closed_now
        closed_now = self.request.query_params.get('closed_now', None)
        if open_now is not None or closed_now is not None:
243
244
245
246
247
248
249
250
            # List of all open facilities
            open_facilities = []
            for facility in Facility.objects.all():
                if facility.is_open():
                    # Append the primary key
                    open_facilities.append(facility.pk)
            # Return all Facility objects with the primary keys located in the
            # open_facilities list
David Haynes's avatar
David Haynes committed
251
252
253
254
255
256
            if open_now:
                return Facility.objects.filter(pk__in=open_facilities)
            # Return all Facility objects with the primary keys not located in
            # the open_facilities list
            elif closed_now:
                return Facility.objects.exclude(pk__in=open_facilities)
257
        # Default behavior
258
        else:
259
260
261
            for facility in Facility.objects.all():
                # Remove all special_schedules that have expired
                facility.clean_special_schedules()
David Haynes's avatar
David Haynes committed
262
            return Facility.objects.all()
263

264
class ScheduleViewSet(viewsets.ModelViewSet):
265
    """
266
267
    A period of time between two dates that represents the beginning and end of a "schedule" or rather, a collection of open times for a facility.

268
    GET /api/schedules/
269
    Return all Schedule objects that have not expired. (ie. end_date is before today)
270
271
272
273
274
275
276
277
278
279
280
281
282
283

    Built-in query parameters:

    GET /api/schedules/?search=
    Query parameter that returns objects that match a keyword provided in the search.

    GET /api/schedules/?ordering=
    Query parameter that orders the returned objects based on the provided field to order by.

    Additionally, you can query against any field you like:

    ie.
    GET /api/schedules/?name=southside_main
    will return the Schedule object that has "southside_main" as its name.
284
    """
285
286
287
288
289
290
291
292
293
    # All model fields that are available for filtering
    FILTER_FIELDS = (
        # Schedule fields
        'name',
        'valid_start',
        'valid_end',
    )

    # Associate a serializer with the ViewSet
294
295
    serializer_class = ScheduleSerializer

296
297
298
299
300
301
302
    # Setup filtering
    filter_backends = (filters.SearchFilter, DjangoFilterBackend,
                       filters.OrderingFilter, )
    search_fields = FILTER_FIELDS
    ordering_fields = FILTER_FIELDS
    filter_fields = FILTER_FIELDS

David Haynes's avatar
David Haynes committed
303
    def get_queryset(self):
304
305
306
307
308
309
310
311
312
313
314
315
316
317
        """
        Handle incoming GET requests and enumerate objects that get returned by
        the API.
        """
        # List of all schedules that are outdated
        filter_old_schedules = []
        for schedule in Schedule.objects.all():
            if schedule.valid_end and schedule.valid_start:
                # If the schedule ended before today
                if schedule.valid_end < datetime.date.today():
                    # Add it to the list of objects we are excluding
                    filter_old_schedules.append(schedule.pk)
        # Return all Schedule objects that have not expired
        return Schedule.objects.exclude(pk__in=filter_old_schedules)
David Haynes's avatar
David Haynes committed
318

319
class OpenTimeViewSet(viewsets.ModelViewSet):
320
    """
321
322
323
324
325
326
    Represents a time period when a Facility is open.

    Monday = 0, Sunday = 6.

    These objects are returned within a larger Schedule object and thus are not
    an endpoint that is query-able, so just return everything when requested.
327
    """
328
    # Associate a serializer with the ViewSet
329
    serializer_class = OpenTimeSerializer
David Haynes's avatar
David Haynes committed
330
331

    def get_queryset(self):
332
333
334
335
        """
        Handle incoming GET requests and enumerate objects that get returned by
        the API.
        """
336
        return OpenTime.objects.all()