import datetime
import django_filters
import pytz
from django import forms
from django import utils
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.utils.timezone import override
from recurrence import Recurrence
from rest_framework import filters, permissions, viewsets
from rest_framework.decorators import list_route
from rest_framework.exceptions import ValidationError as DRFValidationError
from rest_framework.response import Response
import serializers
from radioco.apps.api.viewsets import UpdateOnlyModelViewSet
from radioco.apps.global_settings.models import RadiocomConfiguration
from radioco.apps.programmes.models import Programme, Episode
from radioco.apps.schedules.models import Schedule, Transmission
[docs]class ProgrammeFilter(filters.FilterSet):
[docs]class ProgrammeViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissionsOrAnonReadOnly,)
queryset = Programme.objects.all()
filter_backends = (filters.DjangoFilterBackend, filters.OrderingFilter)
filter_class = ProgrammeFilter
serializer_class = serializers.ProgrammeSerializer
lookup_field = 'slug'
[docs] def list(self, request, *args, **kwargs):
data = ProgrammeFilterForm(request.query_params)
if not data.is_valid():
raise DRFValidationError(data.errors)
after = data.cleaned_data['after']
before = data.cleaned_data['before']
# Apply filters to the queryset
programmes = self.filter_queryset(self.get_queryset())
if after:
programmes = programmes.filter(Q(end_date__gte=after) | Q(end_date__isnull=True))
if before:
programmes = programmes.filter(Q(start_date__lte=before) | Q(start_date__isnull=True))
serializer = self.get_serializer(programmes, many=True)
return Response(serializer.data)
[docs]class RadiocomProgrammeViewSet(ProgrammeViewSet):
serializer_class = serializers.RadiocomProgrammeSerializer
[docs]class EpisodeFilter(filters.FilterSet):
programme = django_filters.CharFilter(name="programme__slug")
[docs]class EpisodeViewSet(viewsets.ReadOnlyModelViewSet): # FIXME: allowing creation breaks the view
queryset = Episode.objects.all().select_related('programme')
filter_backends = (filters.DjangoFilterBackend, filters.OrderingFilter)
filter_class = EpisodeFilter
serializer_class = serializers.EpisodeSerializer
[docs]class ScheduleFilter(filters.FilterSet):
programme = django_filters.CharFilter(name="programme__slug")
[docs]class ScheduleViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissionsOrAnonReadOnly,)
queryset = Schedule.objects.all()
filter_backends = (filters.DjangoFilterBackend, filters.OrderingFilter)
filter_class = ScheduleFilter
serializer_class = serializers.ScheduleSerializer
[docs]class TransmissionViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Schedule.objects.all()
filter_backends = (filters.DjangoFilterBackend,) # Transmissions are always order by date
filter_class = ScheduleFilter
serializer_class = serializers.TransmissionSerializer
[docs] def list(self, request, *args, **kwargs):
data = TransmissionForm(request.query_params)
if not data.is_valid():
raise DRFValidationError(data.errors)
requested_timezone = data.cleaned_data.get('timezone')
after = data.cleaned_data['after']
before = data.cleaned_data['before']
tz = requested_timezone or pytz.utc
after_date = tz.localize(datetime.datetime.combine(after, datetime.time()))
before_date = tz.localize(datetime.datetime.combine(before, datetime.time(23, 59, 59)))
# Apply filters to the queryset
schedules = self.filter_queryset(self.get_queryset())
# Filter by active calendar if that filter was not provided
if not data.cleaned_data.get('calendar'):
schedules = schedules.filter(calendar__is_active=True)
transmissions = Transmission.between(
after_date,
before_date,
schedules=schedules
)
serializer = self.get_serializer(transmissions, many=True)
with override(timezone=tz):
return Response(serializer.data)
@list_route()
[docs] def now(self, request):
data = TimezoneForm(request.query_params)
if not data.is_valid():
raise DRFValidationError(data.errors)
requested_timezone = data.cleaned_data.get('timezone')
tz = requested_timezone or pytz.utc
now = utils.timezone.now()
transmissions = Transmission.at(now)
try:
transmission = transmissions.next()
except StopIteration:
return Response(None)
else:
serializer = self.get_serializer(transmission, many=False)
with override(timezone=tz):
return Response(serializer.data)
[docs]class RadiocomTransmissionViewSet(TransmissionViewSet):
serializer_class = serializers.RadiocomTransmissionSerializer
[docs]class TransmissionOperationViewSet(UpdateOnlyModelViewSet):
permission_classes = (permissions.DjangoModelPermissionsOrAnonReadOnly,)
serializer_class = serializers.TransmissionSerializerLight
queryset = Schedule.objects.all()
[docs] def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response('ok')
[docs]class RadiocomStation(viewsets.ReadOnlyModelViewSet):
serializer_class = serializers.RadiocomConfigurationSerializer
[docs] def list(self, request, *args, **kwargs):
serializer = self.get_serializer(RadiocomConfiguration.get_global(), many=False)
return Response(serializer.data)