kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
See #432: expose artists, album and track tags in API
rodzic
102aa6f5ba
commit
aa6bece8df
|
@ -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):
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue