Fix #895: "Display tracks count instead of albums count for artists with no albums"
This commit is contained in:
parent
7e8e21e1d1
commit
2e0883d44c
|
@ -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:
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Artists with no albums will now show track count on artist card (#895)
|
|
@ -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:
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue