Fix #895: "Display tracks count instead of albums count for artists with no albums"

This commit is contained in:
Ciarán Ainsworth 2019-08-20 12:12:41 +02:00 committed by Eliot Berriot
parent 7e8e21e1d1
commit 2e0883d44c
7 changed files with 26 additions and 7 deletions

View File

@ -79,6 +79,7 @@ class ArtistWithAlbumsSerializer(serializers.ModelSerializer):
albums = ArtistAlbumSerializer(many=True, read_only=True) albums = ArtistAlbumSerializer(many=True, read_only=True)
tags = serializers.SerializerMethodField() tags = serializers.SerializerMethodField()
attributed_to = serializers.SerializerMethodField() attributed_to = serializers.SerializerMethodField()
tracks_count = serializers.SerializerMethodField()
class Meta: class Meta:
model = models.Artist model = models.Artist
@ -92,6 +93,7 @@ class ArtistWithAlbumsSerializer(serializers.ModelSerializer):
"is_local", "is_local",
"tags", "tags",
"attributed_to", "attributed_to",
"tracks_count",
) )
def get_tags(self, obj): def get_tags(self, obj):
@ -100,6 +102,9 @@ class ArtistWithAlbumsSerializer(serializers.ModelSerializer):
get_attributed_to = serialize_attributed_to get_attributed_to = serialize_attributed_to
def get_tracks_count(self, o):
return getattr(o, "_tracks_count", None)
class ArtistSimpleSerializer(serializers.ModelSerializer): class ArtistSimpleSerializer(serializers.ModelSerializer):
class Meta: class Meta:

View File

@ -94,7 +94,11 @@ def refetch_obj(obj, queryset):
class ArtistViewSet(common_views.SkipFilterForGetObject, viewsets.ReadOnlyModelViewSet): class ArtistViewSet(common_views.SkipFilterForGetObject, viewsets.ReadOnlyModelViewSet):
queryset = models.Artist.objects.all().select_related("attributed_to") queryset = (
models.Artist.objects.all()
.select_related("attributed_to")
.annotate(_tracks_count=Count("tracks"))
)
serializer_class = serializers.ArtistWithAlbumsSerializer serializer_class = serializers.ArtistWithAlbumsSerializer
permission_classes = [oauth_permissions.ScopePermission] permission_classes = [oauth_permissions.ScopePermission]
required_scope = "libraries" required_scope = "libraries"

View File

@ -62,7 +62,7 @@ def test_artist_with_albums_serializer(factories, to_api_date):
artist = track.artist artist = track.artist
artist = artist.__class__.objects.with_albums().get(pk=artist.pk) artist = artist.__class__.objects.with_albums().get(pk=artist.pk)
album = list(artist.albums.all())[0] album = list(artist.albums.all())[0]
setattr(artist, "_tracks_count", 42)
expected = { expected = {
"id": artist.id, "id": artist.id,
"fid": artist.fid, "fid": artist.fid,
@ -73,6 +73,7 @@ def test_artist_with_albums_serializer(factories, to_api_date):
"albums": [serializers.ArtistAlbumSerializer(album).data], "albums": [serializers.ArtistAlbumSerializer(album).data],
"tags": [], "tags": [],
"attributed_to": federation_serializers.APIActorSerializer(actor).data, "attributed_to": federation_serializers.APIActorSerializer(actor).data,
"tracks_count": 42,
} }
serializer = serializers.ArtistWithAlbumsSerializer(artist) serializer = serializers.ArtistWithAlbumsSerializer(artist)
assert serializer.data == expected assert serializer.data == expected

View File

@ -6,6 +6,7 @@ import urllib.parse
import uuid import uuid
import pytest import pytest
from django.db.models import Count
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
@ -27,7 +28,7 @@ def test_artist_list_serializer(api_request, factories, logged_in_api_client):
).track ).track
artist = track.artist artist = track.artist
request = api_request.get("/") request = api_request.get("/")
qs = artist.__class__.objects.with_albums() qs = artist.__class__.objects.with_albums().annotate(_tracks_count=Count("tracks"))
serializer = serializers.ArtistWithAlbumsSerializer( serializer = serializers.ArtistWithAlbumsSerializer(
qs, many=True, context={"request": request} qs, many=True, context={"request": request}
) )

View File

@ -0,0 +1 @@
Artists with no albums will now show track count on artist card (#895)

View File

@ -1190,6 +1190,10 @@ definitions:
- $ref: "#/definitions/BaseArtist" - $ref: "#/definitions/BaseArtist"
- type: "object" - type: "object"
properties: properties:
tracks_count:
type: "integer"
format: "int64"
example: 42
albums: albums:
type: "array" type: "array"
items: items:

View File

@ -7,10 +7,14 @@
<router-link :title="artist.name" :to="{name: 'library.artists.detail', params: {id: artist.id}}"> <router-link :title="artist.name" :to="{name: 'library.artists.detail', params: {id: artist.id}}">
{{ artist.name|truncate(30) }} {{ artist.name|truncate(30) }}
</router-link> </router-link>
<div> <div v-if="artist.albums.length > 0">
<i class="small sound icon"></i> <i class="small sound icon"></i>
<translate translate-context="Content/Artist/Card" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate> <translate translate-context="Content/Artist/Card" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate>
</div> </div>
<div v-else-if="artist.tracks_count">
<i class="small sound icon"></i>
<translate translate-context="Content/Artist/Card" :translate-params="{count: artist.tracks_count}" :translate-n="artist.tracks_count" translate-plural="%{ count } tracks">1 track</translate>
</div>
<tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="artist.tags"></tags-list> <tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="artist.tags"></tags-list>
<play-button <play-button
@ -38,11 +42,10 @@ export default {
return { return {
backend: backend, backend: backend,
initialAlbums: 30, initialAlbums: 30,
showAllAlbums: true showAllAlbums: true,
} }
}, },
computed: { computed: {
imageUrl () { imageUrl () {
let url = '../../../assets/audio/default-cover.png' let url = '../../../assets/audio/default-cover.png'
let cover = this.cover let cover = this.cover
@ -59,7 +62,7 @@ export default {
}).filter((c) => { }).filter((c) => {
return !!c return !!c
})[0] || {} })[0] || {}
} },
} }
} }
</script> </script>