spradio-server-django/savepointradio/api/views/radio.py
2018-04-26 12:18:08 -04:00

206 lines
7.9 KiB
Python

from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.response import Response
from profiles.models import RadioProfile, Rating
from radio.models import Album, Artist, Game, Song
from ..permissions import IsAdminOrReadOnly, IsAuthenticatedAndNotDJ
from ..serializers.profiles import (BasicProfileSerializer,
BasicSongRatingsSerializer,
RateSongSerializer)
from ..serializers.radio import (AlbumSerializer, ArtistSerializer,
GameSerializer, FullSongSerializer,
SongArtistsListSerializer,
FullSongRetrieveSerializer)
class AlbumViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdminOrReadOnly]
serializer_class = AlbumSerializer
def get_queryset(self):
'''
Only send full data to an admin. All regular users get filtered
albums.
'''
if (self.request.user.is_authenticated and
self.request.user.is_staff and
not self.request.user.is_dj):
return Album.objects.all()
return Album.music.available()
class ArtistViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdminOrReadOnly]
serializer_class = ArtistSerializer
def get_queryset(self):
'''
Only send full data to an admin. All regular users get filtered
artists.
'''
if (self.request.user.is_authenticated and
self.request.user.is_staff and
not self.request.user.is_dj):
return Artist.objects.all()
return Artist.music.available()
class GameViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdminOrReadOnly]
serializer_class = GameSerializer
def get_queryset(self):
'''
Only send full data to an admin. All regular users get filtered
games.
'''
if (self.request.user.is_authenticated and
self.request.user.is_staff and
not self.request.user.is_dj):
return Game.objects.all()
return Game.music.available()
class SongViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdminOrReadOnly]
def get_queryset(self):
'''
Only send full data to an admin. All regular users get filtered
songs.
'''
if (self.request.user.is_authenticated and
self.request.user.is_staff and
not self.request.user.is_dj):
return Song.objects.all()
return Song.music.available_songs()
def get_serializer_class(self):
'''
Choose a different serializer based on what action is chosen.
(Thanks to https://stackoverflow.com/questions/22616973/)
'''
if self.action in ['list', 'retrieve']:
return FullSongRetrieveSerializer
return FullSongSerializer
def _artists_change(self, request, remove=False):
song = self.get_object()
serializer = SongArtistsListSerializer(data=request.data)
if serializer.is_valid():
artists = Artist.objects.filter(pk__in=serializer.data['artists'])
for artist in artists:
if remove:
song.artists.remove(artist)
else:
song.artists.add(artist)
song.save()
message = 'Artists {} song.'.format(('added to',
'removed from')[remove])
return Response({'detail': message})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
def artists_add(self, request, pk=None):
return self._artists_change(request)
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
def artists_remove(self, request, pk=None):
return self._artists_change(request, remove=True)
@action(detail=True, permission_classes=[AllowAny])
def favorites(self, request, pk=None):
song = self.get_object()
profiles = song.song_favorites.all().order_by('user__name')
page = self.paginate_queryset(profiles)
if page is not None:
serializer = BasicProfileSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = BasicProfileSerializer(profiles, many=True)
return Response(serializer.data)
@action(methods=['post'],
detail=True,
permission_classes=[IsAuthenticatedAndNotDJ])
def favorite(self, request, pk=None):
song = self.get_object()
profile = RadioProfile.objects.get(user=request.user)
if song not in profile.favorites.all():
profile.favorites.add(song)
profile.save()
return Response({'detail': 'Song has been added to favorites.'})
message = 'Song is already a favorite.'
return Response({'detail': message},
status=status.HTTP_400_BAD_REQUEST)
@action(methods=['post'],
detail=True,
permission_classes=[IsAuthenticatedAndNotDJ])
def unfavorite(self, request, pk=None):
song = self.get_object()
profile = RadioProfile.objects.get(user=request.user)
if song in profile.favorites.all():
profile.favorites.remove(song)
profile.save()
message = 'Song has been removed from favorites.'
return Response({'detail': message})
message = 'Song is already not a favorite.'
return Response({'detail': message},
status=status.HTTP_400_BAD_REQUEST)
@action(detail=True, permission_classes=[AllowAny])
def ratings(self, request, pk=None):
song = self.get_object()
ratings = song.rating_set.all().order_by('-created_date')
page = self.paginate_queryset(ratings)
if page is not None:
serializer = BasicSongRatingsSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = BasicSongRatingsSerializer(ratings, many=True)
return Response(serializer.data)
@action(methods=['post'],
detail=True,
permission_classes=[IsAuthenticatedAndNotDJ])
def rate(self, request, pk=None):
serializer = RateSongSerializer(data=request.data)
if serializer.is_valid():
song = self.get_object()
profile = RadioProfile.objects.get(user=request.user)
if 'value' in serializer.data:
rating, created = Rating.objects.update_or_create(
profile=profile,
song=song,
defaults={'value': serializer.data['value']}
)
message = 'Rating {} song.'.format(('updated for',
'created for')[created])
return Response({'detail': message})
message = 'Missing integer \'value\' for song rating.'
return Response({'detail': message},
status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@action(methods=['post'],
detail=True,
permission_classes=[IsAuthenticatedAndNotDJ])
def unrate(self, request, pk=None):
song = self.get_object()
profile = RadioProfile.objects.get(user=request.user)
rating = song.rating_set.filter(profile=profile)
if rating:
rating.delete()
return Response({'detail': 'Rating deleted from song.'})
message = 'Cannot delete nonexistant rating.'
return Response({'detail': message},
status=status.HTTP_400_BAD_REQUEST)