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

281 lines
11 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
2019-06-04 18:58:52 +00:00
from radio.models import Album, Artist, Game, Song, Store
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,
2019-06-04 18:58:52 +00:00
GameSerializer, StoreSerializer,
SongSerializer, SongListSerializer,
SongRetrieveSerializer,
SongArtistsListSerializer,
SongStoresSerializer)
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
2019-06-04 18:58:52 +00:00
class StoreViewSet(viewsets.ModelViewSet):
queryset = Store.objects.all()
permission_classes = [IsAdminUser]
serializer_class = StoreSerializer
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'])
2019-06-04 18:58:52 +00:00
for artist in artists:
if remove:
song.artists.remove(artist)
else:
song.artists.add(artist)
2019-06-04 18:58:52 +00:00
song.save()
2019-06-04 18:58:52 +00:00
if song.artists.count() == 0:
song.disable('No artists specified for song.')
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
2019-06-04 18:58:52 +00:00
def _store_change(self, request, remove=False):
song = self.get_object()
serializer = SongStoresSerializer(data=request.data)
if serializer.is_valid():
try:
store = Store.objects.get(pk=serializer.data['store'])
except Store.DoesNotExist:
return Response({'detail': 'Store does not exist.'},
status=status.HTTP_400_BAD_REQUEST)
if remove:
song.stores.remove(store)
else:
song.stores.add(store)
if serializer.data['set_active'] and not remove:
song.active_store = store
song.save()
if song.stores.count() == 0:
song.disable('No stores specified for song.')
message = 'Store {} 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 store_add(self, request, pk=None):
'''Adds a data store to a song.'''
return self._store_change(request)
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
def store_remove(self, request, pk=None):
'''Removes a data store from a song.'''
return self._store_change(request, remove=True)
@action(detail=True, permission_classes=[IsAdminUser])
def stores(self, request, pk=None):
'''Get a list of data stores associate with this song.'''
song = self.get_object()
stores = song.stores.all().order_by('-created_date')
page = self.paginate_queryset(stores)
if page is not None:
serializer = StoreSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = StoreSerializer(stores, many=True)
return Response(serializer.data)
@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)