Updated API for new Stores and general cleanup.
This commit is contained in:
parent
3afc5c7a3a
commit
c305a32717
4 changed files with 91 additions and 27 deletions
|
@ -4,7 +4,7 @@ from rest_framework.serializers import (IntegerField, ModelSerializer,
|
||||||
Serializer)
|
Serializer)
|
||||||
|
|
||||||
from profiles.models import RadioProfile, SongRequest, Rating
|
from profiles.models import RadioProfile, SongRequest, Rating
|
||||||
from .radio import BasicSongRetrieveSerializer
|
from .radio import SongMinimalSerializer
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
@ -44,7 +44,7 @@ class RateSongSerializer(Serializer):
|
||||||
|
|
||||||
class HistorySerializer(ModelSerializer):
|
class HistorySerializer(ModelSerializer):
|
||||||
profile = BasicProfileSerializer()
|
profile = BasicProfileSerializer()
|
||||||
song = BasicSongRetrieveSerializer()
|
song = SongMinimalSerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SongRequest
|
model = SongRequest
|
||||||
|
@ -52,7 +52,7 @@ class HistorySerializer(ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class BasicProfileRatingsSerializer(ModelSerializer):
|
class BasicProfileRatingsSerializer(ModelSerializer):
|
||||||
song = BasicSongRetrieveSerializer()
|
song = SongMinimalSerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Rating
|
model = Rating
|
||||||
|
|
|
@ -1,71 +1,127 @@
|
||||||
from rest_framework.serializers import (IntegerField, ListField,
|
from rest_framework.serializers import (DecimalField, IntegerField, ListField,
|
||||||
ModelSerializer, Serializer,
|
ModelSerializer, Serializer,
|
||||||
|
SerializerMethodField,
|
||||||
StringRelatedField)
|
StringRelatedField)
|
||||||
|
|
||||||
|
from core.utils import iri_to_path
|
||||||
from radio.models import Album, Artist, Game, Song
|
from radio.models import Album, Artist, Game, Song
|
||||||
|
|
||||||
|
|
||||||
class AlbumSerializer(ModelSerializer):
|
class AlbumSerializer(ModelSerializer):
|
||||||
|
'''A base serializer for an album model.'''
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Album
|
model = Album
|
||||||
fields = ('id', 'title')
|
fields = ('id', 'title')
|
||||||
|
|
||||||
|
|
||||||
class ArtistSerializer(ModelSerializer):
|
class ArtistSerializer(ModelSerializer):
|
||||||
|
'''A base serializer for an artist model.'''
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Artist
|
model = Artist
|
||||||
fields = ('id', 'alias', 'first_name', 'last_name')
|
fields = ('id', 'alias', 'first_name', 'last_name')
|
||||||
|
|
||||||
|
|
||||||
class ArtistFullnameSerializer(ModelSerializer):
|
class ArtistFullnameSerializer(ModelSerializer):
|
||||||
|
'''
|
||||||
|
A base serializer for an artist model, but combining all name
|
||||||
|
attributes into one field.
|
||||||
|
'''
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Artist
|
model = Artist
|
||||||
fields = ('id', 'full_name')
|
fields = ('id', 'full_name')
|
||||||
|
|
||||||
|
|
||||||
class GameSerializer(ModelSerializer):
|
class GameSerializer(ModelSerializer):
|
||||||
|
'''A base serializer for a game model.'''
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Game
|
model = Game
|
||||||
fields = ('id', 'title')
|
fields = ('id', 'title')
|
||||||
|
|
||||||
|
|
||||||
class BasicSongSerializer(ModelSerializer):
|
class SongSerializer(ModelSerializer):
|
||||||
class Meta:
|
'''A base serializer for a song model.'''
|
||||||
model = Song
|
length = DecimalField(
|
||||||
fields = ('id', 'album', 'artists', 'game', 'title', 'average_rating',
|
max_digits=10,
|
||||||
'is_requestable')
|
decimal_places=2,
|
||||||
|
source='current_store.length'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FullSongSerializer(ModelSerializer):
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Song
|
model = Song
|
||||||
fields = ('id', 'album', 'artists', 'published_date', 'game',
|
fields = ('id', 'album', 'artists', 'published_date', 'game',
|
||||||
'num_played', 'last_played', 'length', 'song_type', 'title',
|
'num_played', 'last_played', 'length', 'next_play',
|
||||||
'average_rating', 'is_requestable')
|
'song_type', 'title', 'average_rating', 'is_requestable')
|
||||||
|
|
||||||
|
|
||||||
class BasicSongRetrieveSerializer(BasicSongSerializer):
|
class SongMinimalSerializer(ModelSerializer):
|
||||||
|
'''Minimal song information, usually appended to favorites/ratings.'''
|
||||||
album = AlbumSerializer()
|
album = AlbumSerializer()
|
||||||
artists = ArtistFullnameSerializer(many=True)
|
artists = ArtistFullnameSerializer(many=True)
|
||||||
game = GameSerializer()
|
game = GameSerializer()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Song
|
||||||
|
fields = ('id', 'album', 'artists', 'game', 'title')
|
||||||
|
|
||||||
class FullSongRetrieveSerializer(FullSongSerializer):
|
|
||||||
|
class SongListSerializer(ModelSerializer):
|
||||||
|
'''Song information used in large listings.'''
|
||||||
|
album = AlbumSerializer()
|
||||||
|
artists = ArtistFullnameSerializer(many=True)
|
||||||
|
game = GameSerializer()
|
||||||
|
length = DecimalField(
|
||||||
|
max_digits=10,
|
||||||
|
decimal_places=2,
|
||||||
|
source='current_store.length'
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Song
|
||||||
|
fields = ('id', 'album', 'artists', 'game', 'title', 'average_rating',
|
||||||
|
'length', 'is_requestable')
|
||||||
|
|
||||||
|
|
||||||
|
class SongRetrieveSerializer(SongSerializer):
|
||||||
|
'''
|
||||||
|
An almost complete listing of a song's information, based on a single
|
||||||
|
object retrieval.
|
||||||
|
'''
|
||||||
album = AlbumSerializer()
|
album = AlbumSerializer()
|
||||||
artists = ArtistSerializer(many=True)
|
artists = ArtistSerializer(many=True)
|
||||||
game = GameSerializer()
|
game = GameSerializer()
|
||||||
|
|
||||||
|
|
||||||
class RadioSongSerializer(ModelSerializer):
|
class RadioSongSerializer(ModelSerializer):
|
||||||
|
'''
|
||||||
|
A song serializer that is specific to the radio DJ and the underlying
|
||||||
|
audio manipulation application.
|
||||||
|
'''
|
||||||
album = StringRelatedField()
|
album = StringRelatedField()
|
||||||
artists = StringRelatedField(many=True)
|
artists = StringRelatedField(many=True)
|
||||||
game = StringRelatedField()
|
game = StringRelatedField()
|
||||||
|
length = DecimalField(
|
||||||
|
max_digits=10,
|
||||||
|
decimal_places=2,
|
||||||
|
source='current_store.length'
|
||||||
|
)
|
||||||
|
path = SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Song
|
model = Song
|
||||||
fields = ('album', 'artists', 'game', 'song_type', 'title', 'length',
|
fields = ('album', 'artists', 'game', 'song_type', 'title', 'length',
|
||||||
'path')
|
'path')
|
||||||
|
|
||||||
|
def get_path(self, obj):
|
||||||
|
'''Converts the IRI into a filesystem path.'''
|
||||||
|
iri = str(obj.current_store.iri)
|
||||||
|
if iri.startswith('file://'):
|
||||||
|
return iri_to_path(iri)
|
||||||
|
return iri
|
||||||
|
|
||||||
|
|
||||||
class SongArtistsListSerializer(Serializer):
|
class SongArtistsListSerializer(Serializer):
|
||||||
|
'''
|
||||||
|
A serializer for adding or removing artists from a song based on
|
||||||
|
the song's id number.
|
||||||
|
'''
|
||||||
artists = ListField(child=IntegerField(), min_length=1, max_length=10)
|
artists = ListField(child=IntegerField(), min_length=1, max_length=10)
|
||||||
|
|
|
@ -11,7 +11,7 @@ from ..serializers.profiles import (BasicProfileSerializer,
|
||||||
FullProfileSerializer,
|
FullProfileSerializer,
|
||||||
HistorySerializer,
|
HistorySerializer,
|
||||||
BasicProfileRatingsSerializer)
|
BasicProfileRatingsSerializer)
|
||||||
from ..serializers.radio import BasicSongRetrieveSerializer
|
from ..serializers.radio import SongListSerializer
|
||||||
|
|
||||||
|
|
||||||
class ProfileViewSet(viewsets.ModelViewSet):
|
class ProfileViewSet(viewsets.ModelViewSet):
|
||||||
|
@ -52,10 +52,10 @@ class ProfileViewSet(viewsets.ModelViewSet):
|
||||||
|
|
||||||
page = self.paginate_queryset(favorites)
|
page = self.paginate_queryset(favorites)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
serializer = BasicSongRetrieveSerializer(page, many=True)
|
serializer = SongListSerializer(page, many=True)
|
||||||
return self.get_paginated_response(serializer.data)
|
return self.get_paginated_response(serializer.data)
|
||||||
|
|
||||||
serializer = BasicSongRetrieveSerializer(favorites, many=True)
|
serializer = SongListSerializer(favorites, many=True)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
@action(detail=True, permission_classes=[AllowAny])
|
@action(detail=True, permission_classes=[AllowAny])
|
||||||
|
|
|
@ -10,9 +10,9 @@ from ..serializers.profiles import (BasicProfileSerializer,
|
||||||
BasicSongRatingsSerializer,
|
BasicSongRatingsSerializer,
|
||||||
RateSongSerializer)
|
RateSongSerializer)
|
||||||
from ..serializers.radio import (AlbumSerializer, ArtistSerializer,
|
from ..serializers.radio import (AlbumSerializer, ArtistSerializer,
|
||||||
GameSerializer, FullSongSerializer,
|
GameSerializer, SongSerializer,
|
||||||
SongArtistsListSerializer,
|
SongListSerializer, SongRetrieveSerializer,
|
||||||
FullSongRetrieveSerializer)
|
SongArtistsListSerializer)
|
||||||
|
|
||||||
|
|
||||||
class AlbumViewSet(viewsets.ModelViewSet):
|
class AlbumViewSet(viewsets.ModelViewSet):
|
||||||
|
@ -83,9 +83,11 @@ class SongViewSet(viewsets.ModelViewSet):
|
||||||
|
|
||||||
(Thanks to https://stackoverflow.com/questions/22616973/)
|
(Thanks to https://stackoverflow.com/questions/22616973/)
|
||||||
'''
|
'''
|
||||||
if self.action in ['list', 'retrieve']:
|
if self.action == 'list':
|
||||||
return FullSongRetrieveSerializer
|
return SongListSerializer
|
||||||
return FullSongSerializer
|
if self.action == 'retrieve':
|
||||||
|
return SongRetrieveSerializer
|
||||||
|
return SongSerializer
|
||||||
|
|
||||||
def _artists_change(self, request, remove=False):
|
def _artists_change(self, request, remove=False):
|
||||||
song = self.get_object()
|
song = self.get_object()
|
||||||
|
@ -101,20 +103,21 @@ class SongViewSet(viewsets.ModelViewSet):
|
||||||
message = 'Artists {} song.'.format(('added to',
|
message = 'Artists {} song.'.format(('added to',
|
||||||
'removed from')[remove])
|
'removed from')[remove])
|
||||||
return Response({'detail': message})
|
return Response({'detail': message})
|
||||||
else:
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||||
return Response(serializer.errors,
|
|
||||||
status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
|
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
|
||||||
def artists_add(self, request, pk=None):
|
def artists_add(self, request, pk=None):
|
||||||
|
'''Adds an artist to a song.'''
|
||||||
return self._artists_change(request)
|
return self._artists_change(request)
|
||||||
|
|
||||||
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
|
@action(methods=['post'], detail=True, permission_classes=[IsAdminUser])
|
||||||
def artists_remove(self, request, pk=None):
|
def artists_remove(self, request, pk=None):
|
||||||
|
'''Removes an artist from a song.'''
|
||||||
return self._artists_change(request, remove=True)
|
return self._artists_change(request, remove=True)
|
||||||
|
|
||||||
@action(detail=True, permission_classes=[AllowAny])
|
@action(detail=True, permission_classes=[AllowAny])
|
||||||
def favorites(self, request, pk=None):
|
def favorites(self, request, pk=None):
|
||||||
|
'''Get a list of users who added this song to their favorites list.'''
|
||||||
song = self.get_object()
|
song = self.get_object()
|
||||||
profiles = song.song_favorites.all().order_by('user__name')
|
profiles = song.song_favorites.all().order_by('user__name')
|
||||||
|
|
||||||
|
@ -130,6 +133,7 @@ class SongViewSet(viewsets.ModelViewSet):
|
||||||
detail=True,
|
detail=True,
|
||||||
permission_classes=[IsAuthenticatedAndNotDJ])
|
permission_classes=[IsAuthenticatedAndNotDJ])
|
||||||
def favorite(self, request, pk=None):
|
def favorite(self, request, pk=None):
|
||||||
|
'''Add a song to the user's favorites list.'''
|
||||||
song = self.get_object()
|
song = self.get_object()
|
||||||
profile = RadioProfile.objects.get(user=request.user)
|
profile = RadioProfile.objects.get(user=request.user)
|
||||||
if song not in profile.favorites.all():
|
if song not in profile.favorites.all():
|
||||||
|
@ -144,6 +148,7 @@ class SongViewSet(viewsets.ModelViewSet):
|
||||||
detail=True,
|
detail=True,
|
||||||
permission_classes=[IsAuthenticatedAndNotDJ])
|
permission_classes=[IsAuthenticatedAndNotDJ])
|
||||||
def unfavorite(self, request, pk=None):
|
def unfavorite(self, request, pk=None):
|
||||||
|
'''Remove a song from the user's favorites list.'''
|
||||||
song = self.get_object()
|
song = self.get_object()
|
||||||
profile = RadioProfile.objects.get(user=request.user)
|
profile = RadioProfile.objects.get(user=request.user)
|
||||||
if song in profile.favorites.all():
|
if song in profile.favorites.all():
|
||||||
|
@ -157,6 +162,7 @@ class SongViewSet(viewsets.ModelViewSet):
|
||||||
|
|
||||||
@action(detail=True, permission_classes=[AllowAny])
|
@action(detail=True, permission_classes=[AllowAny])
|
||||||
def ratings(self, request, pk=None):
|
def ratings(self, request, pk=None):
|
||||||
|
'''Get a list of a song's ratings.'''
|
||||||
song = self.get_object()
|
song = self.get_object()
|
||||||
ratings = song.rating_set.all().order_by('-created_date')
|
ratings = song.rating_set.all().order_by('-created_date')
|
||||||
|
|
||||||
|
@ -172,6 +178,7 @@ class SongViewSet(viewsets.ModelViewSet):
|
||||||
detail=True,
|
detail=True,
|
||||||
permission_classes=[IsAuthenticatedAndNotDJ])
|
permission_classes=[IsAuthenticatedAndNotDJ])
|
||||||
def rate(self, request, pk=None):
|
def rate(self, request, pk=None):
|
||||||
|
'''Add a user's rating to a song.'''
|
||||||
serializer = RateSongSerializer(data=request.data)
|
serializer = RateSongSerializer(data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
song = self.get_object()
|
song = self.get_object()
|
||||||
|
@ -195,6 +202,7 @@ class SongViewSet(viewsets.ModelViewSet):
|
||||||
detail=True,
|
detail=True,
|
||||||
permission_classes=[IsAuthenticatedAndNotDJ])
|
permission_classes=[IsAuthenticatedAndNotDJ])
|
||||||
def unrate(self, request, pk=None):
|
def unrate(self, request, pk=None):
|
||||||
|
'''Remove a user's rating from a song.'''
|
||||||
song = self.get_object()
|
song = self.get_object()
|
||||||
profile = RadioProfile.objects.get(user=request.user)
|
profile = RadioProfile.objects.get(user=request.user)
|
||||||
rating = song.rating_set.filter(profile=profile)
|
rating = song.rating_set.filter(profile=profile)
|
||||||
|
|
Loading…
Reference in a new issue