class ArtistViewSet( 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.ArtistWithAlbumsSerializer 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 = action(methods=["get"], detail=True)( get_libraries(filter_uploads=lambda o, uploads: uploads.filter( Q(track__artist=o) | Q(track__album__artist=o))))
class TrackViewSet( HandleInvalidSearch, common_views.SkipFilterForGetObject, mixins.DestroyModelMixin, viewsets.ReadOnlyModelViewSet, ): """ A simple ViewSet for viewing and editing accounts. """ queryset = ( models.Track.objects.all() .for_nested_serialization() .prefetch_related("attributed_to", "attachment_cover") .order_by("-creation_date") ) serializer_class = serializers.TrackSerializer permission_classes = [oauth_permissions.ScopePermission] required_scope = "libraries" anonymous_policy = "setting" filterset_class = filters.TrackFilter ordering_fields = ( "creation_date", "title", "album__title", "album__release_date", "size", "position", "disc_number", "artist__name", "artist__modification_date", ) 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_queryset(self): queryset = super().get_queryset() if self.action in ["destroy"]: queryset = queryset.exclude(artist__channel=None).filter( artist__attributed_to=self.request.user.actor ) filter_favorites = self.request.GET.get("favorites", None) user = self.request.user if user.is_authenticated and filter_favorites == "true": queryset = queryset.filter(track_favorites__user=user) queryset = queryset.with_playable_uploads( utils.get_actor_from_request(self.request) ) return queryset.prefetch_related(TAG_PREFETCH) libraries = action(methods=["get"], detail=True)( get_libraries(filter_uploads=lambda o, uploads: uploads.filter(track=o)) ) def get_serializer_context(self): context = super().get_serializer_context() context["description"] = self.action in ["retrieve", "create", "update"] return context @transaction.atomic def perform_destroy(self, instance): uploads = instance.uploads.order_by("id") routes.outbox.dispatch( {"type": "Delete", "object": {"type": "Audio"}}, context={"uploads": list(uploads)}, ) instance.delete()
class AlbumViewSet( HandleInvalidSearch, common_views.SkipFilterForGetObject, mixins.CreateModelMixin, mixins.DestroyModelMixin, viewsets.ReadOnlyModelViewSet, ): queryset = ( models.Album.objects.all() .order_by("-creation_date") .prefetch_related("artist", "attributed_to", "attachment_cover") ) serializer_class = serializers.AlbumSerializer permission_classes = [oauth_permissions.ScopePermission] required_scope = "libraries" anonymous_policy = "setting" ordering_fields = ( "creation_date", "release_date", "title", "artist__modification_date", ) filterset_class = filters.AlbumFilter 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", ] context["user"] = self.request.user return context def get_queryset(self): queryset = super().get_queryset() if self.action in ["destroy"]: queryset = queryset.exclude(artist__channel=None).filter( artist__attributed_to=self.request.user.actor ) tracks = ( models.Track.objects.prefetch_related("artist") .with_playable_uploads(utils.get_actor_from_request(self.request)) .order_for_album() ) qs = queryset.prefetch_related( Prefetch("tracks", queryset=tracks), TAG_PREFETCH ) return qs libraries = action(methods=["get"], detail=True)( get_libraries(filter_uploads=lambda o, uploads: uploads.filter(track__album=o)) ) def get_serializer_class(self): if self.action in ["create"]: return serializers.AlbumCreateSerializer return super().get_serializer_class() @transaction.atomic def perform_destroy(self, instance): routes.outbox.dispatch( {"type": "Delete", "object": {"type": "Album"}}, context={"album": instance}, ) models.Album.objects.filter(pk=instance.pk).delete()
class V(viewsets.ModelViewSet): queryset = music_models.Track.objects.all() mutations = decorators.mutations_route(types=["update"]) permission_classes = []