See #432: expose artists, album and track tags in API

environments/review-front-arti-0habim/deployments/2230
Eliot Berriot 2019-07-15 13:58:22 +02:00
rodzic 102aa6f5ba
commit aa6bece8df
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: DD6965E2476E5C27
4 zmienionych plików z 62 dodań i 8 usunięć

Wyświetl plik

@ -67,10 +67,24 @@ class ArtistAlbumSerializer(serializers.ModelSerializer):
class ArtistWithAlbumsSerializer(serializers.ModelSerializer):
albums = ArtistAlbumSerializer(many=True, read_only=True)
tags = serializers.SerializerMethodField()
class Meta:
model = models.Artist
fields = ("id", "fid", "mbid", "name", "creation_date", "albums", "is_local")
fields = (
"id",
"fid",
"mbid",
"name",
"creation_date",
"albums",
"is_local",
"tags",
)
def get_tags(self, obj):
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
return [ti.tag.name for ti in tagged_items]
class ArtistSimpleSerializer(serializers.ModelSerializer):
@ -124,6 +138,7 @@ class AlbumSerializer(serializers.ModelSerializer):
artist = ArtistSimpleSerializer(read_only=True)
cover = cover_field
is_playable = serializers.SerializerMethodField()
tags = serializers.SerializerMethodField()
class Meta:
model = models.Album
@ -139,6 +154,7 @@ class AlbumSerializer(serializers.ModelSerializer):
"creation_date",
"is_playable",
"is_local",
"tags",
)
def get_tracks(self, o):
@ -153,6 +169,10 @@ class AlbumSerializer(serializers.ModelSerializer):
except AttributeError:
return None
def get_tags(self, obj):
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
return [ti.tag.name for ti in tagged_items]
class TrackAlbumSerializer(serializers.ModelSerializer):
artist = ArtistSimpleSerializer(read_only=True)
@ -192,6 +212,7 @@ class TrackSerializer(serializers.ModelSerializer):
album = TrackAlbumSerializer(read_only=True)
uploads = serializers.SerializerMethodField()
listen_url = serializers.SerializerMethodField()
tags = serializers.SerializerMethodField()
class Meta:
model = models.Track
@ -210,6 +231,7 @@ class TrackSerializer(serializers.ModelSerializer):
"copyright",
"license",
"is_local",
"tags",
)
def get_listen_url(self, obj):
@ -219,6 +241,10 @@ class TrackSerializer(serializers.ModelSerializer):
uploads = getattr(obj, "playable_uploads", [])
return TrackUploadSerializer(uploads, many=True).data
def get_tags(self, obj):
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
return [ti.tag.name for ti in tagged_items]
@common_serializers.track_fields_for_update("name", "description", "privacy_level")
class LibraryForOwnerSerializer(serializers.ModelSerializer):

Wyświetl plik

@ -23,13 +23,19 @@ from funkwhale_api.federation import actors
from funkwhale_api.federation import api_serializers as federation_api_serializers
from funkwhale_api.federation import decorators as federation_decorators
from funkwhale_api.federation import routes
from funkwhale_api.tags.models import Tag
from funkwhale_api.tags.models import Tag, TaggedItem
from funkwhale_api.users.oauth import permissions as oauth_permissions
from . import filters, licenses, models, serializers, tasks, utils
logger = logging.getLogger(__name__)
TAG_PREFETCH = Prefetch(
"tagged_items",
queryset=TaggedItem.objects.all().select_related().order_by("tag__name"),
to_attr="_prefetched_tagged_items",
)
def get_libraries(filter_uploads):
def libraries(self, request, *args, **kwargs):
@ -71,7 +77,9 @@ class ArtistViewSet(common_views.SkipFilterForGetObject, viewsets.ReadOnlyModelV
albums = albums.annotate_playable_by_actor(
utils.get_actor_from_request(self.request)
)
return queryset.prefetch_related(Prefetch("albums", queryset=albums))
return queryset.prefetch_related(
Prefetch("albums", queryset=albums), TAG_PREFETCH
)
libraries = action(methods=["get"], detail=True)(
get_libraries(
@ -103,7 +111,9 @@ class AlbumViewSet(common_views.SkipFilterForGetObject, viewsets.ReadOnlyModelVi
.with_playable_uploads(utils.get_actor_from_request(self.request))
.order_for_album()
)
qs = queryset.prefetch_related(Prefetch("tracks", queryset=tracks))
qs = queryset.prefetch_related(
Prefetch("tracks", queryset=tracks), TAG_PREFETCH
)
return qs
libraries = action(methods=["get"], detail=True)(
@ -206,7 +216,7 @@ class TrackViewSet(common_views.SkipFilterForGetObject, viewsets.ReadOnlyModelVi
queryset = queryset.with_playable_uploads(
utils.get_actor_from_request(self.request)
)
return queryset
return queryset.prefetch_related(TAG_PREFETCH)
libraries = action(methods=["get"], detail=True)(
get_libraries(filter_uploads=lambda o, uploads: uploads.filter(track=o))

Wyświetl plik

@ -69,6 +69,7 @@ def test_artist_with_albums_serializer(factories, to_api_date):
"is_local": artist.is_local,
"creation_date": to_api_date(artist.creation_date),
"albums": [serializers.ArtistAlbumSerializer(album).data],
"tags": [],
}
serializer = serializers.ArtistWithAlbumsSerializer(artist)
assert serializer.data == expected
@ -175,6 +176,7 @@ def test_album_serializer(factories, to_api_date):
"release_date": to_api_date(album.release_date),
"tracks": serializers.AlbumTrackSerializer([track2, track1], many=True).data,
"is_local": album.is_local,
"tags": [],
}
serializer = serializers.AlbumSerializer(album)
@ -202,6 +204,7 @@ def test_track_serializer(factories, to_api_date):
"license": upload.track.license.code,
"copyright": upload.track.copyright,
"is_local": upload.track.is_local,
"tags": [],
}
serializer = serializers.TrackSerializer(track)
assert serializer.data == expected

Wyświetl plik

@ -16,8 +16,11 @@ DATA_DIR = os.path.dirname(os.path.abspath(__file__))
def test_artist_list_serializer(api_request, factories, logged_in_api_client):
tags = ["tag1", "tag2"]
track = factories["music.Upload"](
library__privacy_level="everyone", import_status="finished"
library__privacy_level="everyone",
import_status="finished",
track__album__artist__set_tags=tags,
).track
artist = track.artist
request = api_request.get("/")
@ -27,8 +30,10 @@ def test_artist_list_serializer(api_request, factories, logged_in_api_client):
)
expected = {"count": 1, "next": None, "previous": None, "results": serializer.data}
for artist in serializer.data:
artist["tags"] = tags
for album in artist["albums"]:
album["is_playable"] = True
url = reverse("api:v1:artists-list")
response = logged_in_api_client.get(url)
@ -37,8 +42,11 @@ def test_artist_list_serializer(api_request, factories, logged_in_api_client):
def test_album_list_serializer(api_request, factories, logged_in_api_client):
tags = ["tag1", "tag2"]
track = factories["music.Upload"](
library__privacy_level="everyone", import_status="finished"
library__privacy_level="everyone",
import_status="finished",
track__album__set_tags=tags,
).track
album = track.album
request = api_request.get("/")
@ -47,6 +55,8 @@ def test_album_list_serializer(api_request, factories, logged_in_api_client):
qs, many=True, context={"request": request}
)
expected = {"count": 1, "next": None, "previous": None, "results": serializer.data}
for album in serializer.data:
album["tags"] = tags
url = reverse("api:v1:albums-list")
response = logged_in_api_client.get(url)
@ -55,8 +65,11 @@ def test_album_list_serializer(api_request, factories, logged_in_api_client):
def test_track_list_serializer(api_request, factories, logged_in_api_client):
tags = ["tag1", "tag2"]
track = factories["music.Upload"](
library__privacy_level="everyone", import_status="finished"
library__privacy_level="everyone",
import_status="finished",
track__set_tags=tags,
).track
request = api_request.get("/")
qs = track.__class__.objects.with_playable_uploads(None)
@ -64,6 +77,8 @@ def test_track_list_serializer(api_request, factories, logged_in_api_client):
qs, many=True, context={"request": request}
)
expected = {"count": 1, "next": None, "previous": None, "results": serializer.data}
for track in serializer.data:
track["tags"] = tags
url = reverse("api:v1:tracks-list")
response = logged_in_api_client.get(url)