spradio-server-django/savepointradio/api/views/radio.py

215 lines
8.3 KiB
Python
Raw Normal View History

from rest_framework import status, viewsets
from rest_framework.decorators import action
2018-04-09 16:11:15 +00:00
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.response import Response
2018-03-28 20:12:55 +00:00
2018-04-09 16:11:15 +00:00
from profiles.models import RadioProfile, Rating
2018-03-28 20:12:55 +00:00
from radio.models import Album, Artist, Game, Song
2018-04-09 16:11:15 +00:00
from ..permissions import IsAdminOrReadOnly, IsAuthenticatedAndNotDJ
from ..serializers.profiles import (BasicProfileSerializer,
BasicSongRatingsSerializer,
2018-04-09 16:11:15 +00:00
RateSongSerializer)
2018-03-28 20:12:55 +00:00
from ..serializers.radio import (AlbumSerializer, ArtistSerializer,
GameSerializer, SongSerializer,
SongListSerializer, SongRetrieveSerializer,
SongArtistsListSerializer)
2018-03-28 20:12:55 +00:00
class AlbumViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdminOrReadOnly]
2018-03-28 20:12:55 +00:00
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()
2018-03-28 20:12:55 +00:00
class ArtistViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdminOrReadOnly]
2018-03-28 20:12:55 +00:00
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()
2018-03-28 20:12:55 +00:00
class GameViewSet(viewsets.ModelViewSet):
permission_classes = [IsAdminOrReadOnly]
2018-03-28 20:12:55 +00:00
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()
2018-03-28 20:12:55 +00:00
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 == 'list':
return SongListSerializer
if self.action == 'retrieve':
return SongRetrieveSerializer
return SongSerializer
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})
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):
'''Adds an artist to a song.'''
return self._artists_change(request)
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
def artists_remove(self, request, pk=None):
'''Removes an artist from a song.'''
return self._artists_change(request, remove=True)
2018-04-09 16:11:15 +00:00
@action(detail=True, permission_classes=[AllowAny])
def favorites(self, request, pk=None):
'''Get a list of users who added this song to their favorites list.'''
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):
'''Add a song to the user's favorites list.'''
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):
'''Remove a song from the user's favorites list.'''
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)
2018-04-09 16:11:15 +00:00
@action(detail=True, permission_classes=[AllowAny])
def ratings(self, request, pk=None):
'''Get a list of a song's ratings.'''
2018-04-09 16:11:15 +00:00
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):
'''Add a user's rating to a song.'''
2018-04-09 16:11:15 +00:00
serializer = RateSongSerializer(data=request.data)
if serializer.is_valid():
song = self.get_object()
2018-04-09 16:11:15 +00:00
profile = RadioProfile.objects.get(user=request.user)
if 'value' in serializer.data:
2018-04-09 16:11:15 +00:00
rating, created = Rating.objects.update_or_create(
profile=profile,
song=song,
defaults={'value': serializer.data['value']}
2018-04-09 16:11:15 +00:00
)
message = 'Rating {} song.'.format(('updated for',
'created for')[created])
return Response({'detail': message})
message = 'Missing integer \'value\' for song rating.'
return Response({'detail': message},
2018-04-09 16:11:15 +00:00
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):
'''Remove a user's rating from a song.'''
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)