From bf99e13230ddcd2f6da0ab0b5b3eb660d703b919 Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Thu, 30 Jan 2020 15:00:55 +0100 Subject: [PATCH] See #170: include channel info in artist representations --- api/funkwhale_api/audio/factories.py | 5 +++- api/funkwhale_api/music/models.py | 6 +++++ api/funkwhale_api/music/serializers.py | 15 +++++++++++ api/funkwhale_api/music/views.py | 4 ++- api/tests/music/test_serializers.py | 35 ++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/api/funkwhale_api/audio/factories.py b/api/funkwhale_api/audio/factories.py index ddf4ac9387..3704b4d1d5 100644 --- a/api/funkwhale_api/audio/factories.py +++ b/api/funkwhale_api/audio/factories.py @@ -21,7 +21,10 @@ class ChannelFactory(NoUpdateOnCreate, factory.django.DjangoModelFactory): privacy_level="everyone", ) actor = factory.LazyAttribute(set_actor) - artist = factory.SubFactory(music_factories.ArtistFactory) + artist = factory.SubFactory( + music_factories.ArtistFactory, + attributed_to=factory.SelfAttribute("..attributed_to"), + ) class Meta: model = "audio.Channel" diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index 1d156a6c62..c44175e35a 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -273,6 +273,12 @@ class Artist(APIModelMixin): def cover(self): return self.attachment_cover + def get_channel(self): + try: + return self.channel + except ObjectDoesNotExist: + return None + def import_artist(v): a = Artist.get_or_create_from_api(mbid=v[0]["artist"]["id"])[0] diff --git a/api/funkwhale_api/music/serializers.py b/api/funkwhale_api/music/serializers.py index a6ca51f0aa..281b7d792d 100644 --- a/api/funkwhale_api/music/serializers.py +++ b/api/funkwhale_api/music/serializers.py @@ -103,6 +103,7 @@ class ArtistWithAlbumsSerializer(OptionalDescriptionMixin, serializers.Serialize albums = ArtistAlbumSerializer(many=True) tags = serializers.SerializerMethodField() attributed_to = serializers.SerializerMethodField() + channel = serializers.SerializerMethodField() tracks_count = serializers.SerializerMethodField() id = serializers.IntegerField() fid = serializers.URLField() @@ -123,6 +124,20 @@ class ArtistWithAlbumsSerializer(OptionalDescriptionMixin, serializers.Serialize tracks = getattr(o, "_prefetched_tracks", None) return len(tracks) if tracks else None + def get_channel(self, o): + channel = o.get_channel() + if not channel: + return + + return { + "uuid": str(channel.uuid), + "actor": { + "full_username": channel.actor.full_username, + "preferred_username": channel.actor.preferred_username, + "domain": channel.actor.domain_id, + }, + } + def serialize_artist_simple(artist): data = { diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index a5ddb5abe4..8ca2164f6c 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -115,11 +115,12 @@ class ArtistViewSet( models.Artist.objects.all() .prefetch_related("attributed_to", "attachment_cover") .prefetch_related( + "channel__actor", Prefetch( "tracks", queryset=models.Track.objects.all(), to_attr="_prefetched_tracks", - ) + ), ) .order_by("-id") ) @@ -752,6 +753,7 @@ class Search(views.APIView): models.Artist.objects.all() .filter(query_obj) .with_albums() + .prefetch_related("channel__actor") .select_related("attributed_to") ) return common_utils.order_for_search(qs, "name")[: self.max_results] diff --git a/api/tests/music/test_serializers.py b/api/tests/music/test_serializers.py index 6325ff54b2..ca7d47d6fd 100644 --- a/api/tests/music/test_serializers.py +++ b/api/tests/music/test_serializers.py @@ -73,6 +73,41 @@ def test_artist_with_albums_serializer(factories, to_api_date): "attributed_to": federation_serializers.APIActorSerializer(actor).data, "tracks_count": 42, "cover": common_serializers.AttachmentSerializer(artist.attachment_cover).data, + "channel": None, + } + serializer = serializers.ArtistWithAlbumsSerializer(artist) + assert serializer.data == expected + + +def test_artist_with_albums_serializer_channel(factories, to_api_date): + actor = factories["federation.Actor"]() + channel = factories["audio.Channel"](attributed_to=actor) + track = factories["music.Track"](album__artist=channel.artist) + artist = track.artist + artist = artist.__class__.objects.with_albums().get(pk=artist.pk) + album = list(artist.albums.all())[0] + setattr(artist, "_prefetched_tracks", range(42)) + expected = { + "id": artist.id, + "fid": artist.fid, + "mbid": str(artist.mbid), + "name": artist.name, + "is_local": artist.is_local, + "content_category": artist.content_category, + "creation_date": to_api_date(artist.creation_date), + "albums": [serializers.ArtistAlbumSerializer(album).data], + "tags": [], + "attributed_to": federation_serializers.APIActorSerializer(actor).data, + "tracks_count": 42, + "cover": common_serializers.AttachmentSerializer(artist.attachment_cover).data, + "channel": { + "uuid": str(channel.uuid), + "actor": { + "full_username": channel.actor.full_username, + "preferred_username": channel.actor.preferred_username, + "domain": channel.actor.domain_id, + }, + }, } serializer = serializers.ArtistWithAlbumsSerializer(artist) assert serializer.data == expected -- GitLab