Initial commit

This commit is contained in:
Ciarán Ainsworth 2024-05-12 13:45:17 +02:00
parent f0706ecc5f
commit bbb0d47e1a
No known key found for this signature in database
5 changed files with 106 additions and 0 deletions

View File

@ -7,6 +7,10 @@ router = common_routers.OptionalSlashRouter()
v2_patterns = router.urls
v2_patterns += [
re_path(
r"^artists/",
include(("funkwhale_api.music.urls_v2", "artists"), namespace="artists"),
),
re_path(
r"^instance/",
include(("funkwhale_api.instance.urls_v2", "instance"), namespace="instance"),

View File

@ -202,6 +202,7 @@ class ArtistQuerySet(common_models.LocalFromFidQuerySet, models.QuerySet):
class Artist(APIModelMixin):
guid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
name = models.TextField()
federation_namespace = "artists"
musicbrainz_model = "artist"

View File

@ -1,4 +1,5 @@
import urllib.parse
import uuid
from django import urls
from django.conf import settings
@ -854,3 +855,30 @@ class SearchResultSerializer(serializers.Serializer):
tracks = TrackSerializer(many=True)
albums = AlbumSerializer(many=True)
tags = tags_serializers.TagSerializer(many=True)
class V2_BaseArtistSerializer(serializers.ModelSerializer):
"""
A simple serializer for artist information.
All other serializers that reference an artist should use this serializer.
"""
guid = models.UUIDField(default=uuid.uuid4, editable=False)
fid = serializers.URLField()
mbid = serializers.UUIDField()
name = serializers.CharField()
contentCategory = serializers.CharField()
local = serializers.BooleanField()
cover = CoverField(allow_null=True, required=False)
tags = serializers.SerializerMethodField()
# Fetch all tags associated with the artist.
@extend_schema_field({"type": "array", "items": {"type": "string"}})
def get_tags(self, obj):
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
return [ti.tag.name for ti in tagged_items]
def get_local(artist, upload) -> bool:
return federation_utils.is_local(artist.fid)

View File

@ -0,0 +1,10 @@
from funkwhale_api.common import routers
from . import views
router = routers.OptionalSlashRouter()
router.register(r"artists", views.V2_ArtistsViewSet, "artists")
urlpatterns = router.urls

View File

@ -175,6 +175,69 @@ class ArtistViewSet(
)
class V2_ArtistsViewSet(
HandleInvalidSearch,
common_views.SkipFilterForGetObject,
viewsets.ReadOnlyModelViewSet,
):
queryset = (
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")
)
serializer_class = serializers.V2_BaseArtistSerializer
permission_classes = [oauth_permissions.ScopePermission]
required_scope = "libraries"
anonymous_policy = "setting"
filterset_class = filters.ArtistFilter
fetches = federation_decorators.fetches_route()
mutations = common_decorators.mutations_route(types=["update"])
def get_object(self):
obj = super().get_object()
if (
self.action == "retrieve"
and self.request.GET.get("refresh", "").lower() == "true"
):
obj = refetch_obj(obj, self.get_queryset())
return obj
def get_serializer_context(self):
context = super().get_serializer_context()
context["description"] = self.action in ["retrieve", "create", "update"]
return context
def get_queryset(self):
queryset = super().get_queryset()
albums = (
models.Album.objects.with_tracks_count()
.select_related("attachment_cover")
.prefetch_related("tracks")
)
albums = albums.annotate_playable_by_actor(
utils.get_actor_from_request(self.request)
)
return queryset.prefetch_related(
Prefetch("albums", queryset=albums), TAG_PREFETCH
)
libraries = get_libraries(
lambda o, uploads: uploads.filter(
Q(track__artist=o) | Q(track__album__artist=o)
)
)
class AlbumViewSet(
HandleInvalidSearch,
common_views.SkipFilterForGetObject,