diff --git a/README.rst b/README.rst index 7fd1d23c9d209bfcb9ca35e2566dce015db2a118..4f688797bdfd9d370fa9ad3dc0d741b633c0d1af 100644 --- a/README.rst +++ b/README.rst @@ -37,7 +37,7 @@ Setting up the environment Create a virtual environment where the dependencies will live:: - $ python3 -m venv python + $ python3.8 -m venv python $ source python/bin/activate (python)$ diff --git a/fixtures/program/show.json b/fixtures/program/show.json index cb9c561c20d2b7d6a10d101b29bd8d24d649b595..808817deedaaf4d6e0d8cdea0ff9a13d4651f2d1 100644 --- a/fixtures/program/show.json +++ b/fixtures/program/show.json @@ -18,7 +18,7 @@ "email": "musikredaktion@helsinki.at", "website": null, "cba_series_id": null, - "default_id": null, + "default_playlist_id": null, "created": "1969-12-31T22:00:00Z", "last_updated": "1969-12-31T22:00:00Z", "is_active": true, diff --git a/program/views.py b/program/views.py index 520e003b921424011f1876654a7eb65be44883d4..22cb078908a11b6b696b6aca58979189373d0e4b 100644 --- a/program/views.py +++ b/program/views.py @@ -19,6 +19,7 @@ # import json +import logging from datetime import date, datetime, time, timedelta from django.contrib.auth.models import User @@ -37,6 +38,7 @@ from program.serializers import TypeSerializer, LanguageSerializer, MusicFocusSe UserSerializer from program.utils import get_cached_shows +logger = logging.getLogger(__name__) def json_day_schedule(request, year=None, month=None, day=None): if year is None and month is None and day is None: @@ -469,9 +471,19 @@ class APIScheduleViewSet(viewsets.ModelViewSet): if 'schedule' not in request.data: return Response(status=status.HTTP_400_BAD_REQUEST) + # If we're updating the default playlist id + # TODO: If nothing else than default_playlist_id, automation_id or is_repetition changed -> just save and don't do anything + new_schedule = request.data.get('schedule') + if 'default_playlist_id' in new_schedule: + schedule = get_object_or_404(Schedule, pk=pk, show=show_pk) + schedule.default_playlist_id = int(new_schedule['default_playlist_id']) + schedule.save() + + serializer = ScheduleSerializer(schedule) + return Response(serializer.data) + # First update submit -> return projected timeslots and collisions if 'solutions' not in request.data: - # TODO: If nothing else than default_playlist_id, automation_id or is_repetition changed -> just save and don't do anything return Response(Schedule.make_conflicts(request.data['schedule'], pk, show_pk)) # Otherwise try to resolve @@ -507,6 +519,7 @@ class APITimeSlotViewSet(viewsets.ModelViewSet): /timeslots/{pk} eturns the given timeslot (GET) /timeslots/?start={start_date}&end={end_date} returns timeslots within the time range (GET) /shows/{show_pk}/timeslots returns timeslots of the show (GET, POST) + /shows/{show_pk}/timeslots?surrounding returns the 10 nearest timeslots for the current date (GET) /shows/{show_pk}/timeslots/{pk} returns a timeslots by its ID (GET, PUT, DELETE) /shows/{show_pk}/timeslots/?start={start_date}&end={end_date} returns timeslots of the show within the time range /shows/{show_pk}/schedules/{schedule_pk}/timeslots returns all timeslots of the schedule (GET, POST) @@ -522,7 +535,6 @@ class APITimeSlotViewSet(viewsets.ModelViewSet): def get_queryset(self): show_pk = int_or_none('show_pk', self.kwargs) schedule_pk = int_or_none('schedule_pk', self.kwargs) - # Filters # Return next 60 days by default @@ -533,6 +545,25 @@ class APITimeSlotViewSet(viewsets.ModelViewSet): start = datetime.combine(datetime.strptime(self.request.query_params.get('start'), '%Y-%m-%d').date(), time(0, 0)) end = datetime.combine(datetime.strptime(self.request.query_params.get('end'), '%Y-%m-%d').date(), time(23, 59)) + default_order = '-start' + order = self.request.query_params.get('order', default_order) + + # If someone tries to sort by a field that isn't available on the model + # we silently ignore that and use the default sort order. + model_fields = [field.name for field in TimeSlot._meta.get_fields()] + if order.lstrip('-') not in model_fields: + order = default_order + + + if 'surrounding' in self.request.query_params: + today = datetime.today() + + nearest_timeslots_in_future = TimeSlot.objects.filter(start__gte=today).order_by('start').values_list('id', flat=True)[:5] + nearest_timeslots_in_past = TimeSlot.objects.filter(start__lt=today).order_by('-start').values_list('id', flat=True)[:5] + relevant_timeslot_ids = list(nearest_timeslots_in_future) + list(nearest_timeslots_in_past) + + return TimeSlot.objects.filter(id__in=relevant_timeslot_ids).order_by(order) + # Endpoints # @@ -541,7 +572,7 @@ class APITimeSlotViewSet(viewsets.ModelViewSet): # Returns timeslots of the given show and schedule # if show_pk and schedule_pk: - return TimeSlot.objects.filter(show=show_pk, schedule=schedule_pk, start__gte=start, end__lte=end).order_by('start') + return TimeSlot.objects.filter(show=show_pk, schedule=schedule_pk, start__gte=start, end__lte=end).order_by(order) # # /shows/1/timeslots/ @@ -549,7 +580,7 @@ class APITimeSlotViewSet(viewsets.ModelViewSet): # Returns timeslots of the show # elif show_pk and schedule_pk is None: - return TimeSlot.objects.filter(show=show_pk, start__gte=start, end__lte=end).order_by('start') + return TimeSlot.objects.filter(show=show_pk, start__gte=start, end__lte=end).order_by(order) # # /timeslots/ @@ -557,12 +588,13 @@ class APITimeSlotViewSet(viewsets.ModelViewSet): # Returns all timeslots # else: - return TimeSlot.objects.filter(start__gte=start, end__lte=end).order_by('start') + return TimeSlot.objects.filter(start__gte=start, end__lte=end).order_by(order) def retrieve(self, request, *args, **kwargs): pk = int_or_none('pk', self.kwargs) show_pk = int_or_none('show_pk', self.kwargs) + if show_pk: timeslot = get_object_or_404(TimeSlot, pk=pk, show=show_pk) else: diff --git a/run.sh b/run.sh index b94a9b9d36f0d4894b2b73e0f282a742746f3b55..1907b8ef73c1947c886d10a7c80e86775d576b31 100755 --- a/run.sh +++ b/run.sh @@ -18,8 +18,8 @@ docker="false" # - docker:dev # -if [[ $* =~ ^(init|dev|prod|test|build|push|serve)$ ]]; then - mode=$1 +if [[ $* =~ ^(init|dev|prod|test|build|push|serve)$ ]]; then + mode=$1 fi if [[ "$1" == *"docker:"* ]]; then @@ -41,7 +41,9 @@ if [[ $docker == "false" ]]; then if [[ $mode == "init" ]]; then echo "Creating Python VirtualEnvironment" - virtualenv -p python3.6 python + python3.8 -m venv python + echo "Activate Environment" + source python/bin/activate echo "Install dependencies" pip3 install -r requirements.txt echo "Next you need to create the configuration, run fixtues, migrations and create a superuser."