From 4268fe3aeba4c898f3d0286fad091e22ec535d36 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Tue, 14 Jan 2020 16:18:32 +0100 Subject: [PATCH] See #170: can now filter tracks and albums by channel --- api/funkwhale_api/music/filters.py | 32 ++++++++++++++++++++++++++++-- api/tests/music/test_filters.py | 32 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py index 64b44c8c9..484a078f7 100644 --- a/api/funkwhale_api/music/filters.py +++ b/api/funkwhale_api/music/filters.py @@ -1,6 +1,7 @@ from django_filters import rest_framework as filters from funkwhale_api.audio import filters as audio_filters +from funkwhale_api.audio import models as audio_models from funkwhale_api.common import fields from funkwhale_api.common import filters as common_filters from funkwhale_api.common import search @@ -20,9 +21,30 @@ def filter_tags(queryset, name, value): TAG_FILTER = common_filters.MultipleQueryFilter(method=filter_tags) +class ChannelFilterSet(filters.FilterSet): + + channel = filters.CharFilter(field_name="_", method="filter_channel") + + def filter_channel(self, queryset, name, value): + if not value: + return queryset + + channel = audio_models.Channel.objects.filter(uuid=value).first() + + if not channel: + return queryset.none() + + uploads = models.Upload.objects.filter(library=channel.library) + actor = utils.get_actor_from_request(self.request) + uploads = uploads.playable_by(actor) + ids = uploads.values_list(self.Meta.channel_filter_field, flat=True) + return queryset.filter(pk__in=ids) + + class ArtistFilter( audio_filters.IncludeChannelsFilterSet, moderation_filters.HiddenContentFilterSet ): + q = fields.SearchFilter(search_fields=["name"], fts_search_fields=["body_text"]) playable = filters.BooleanFilter(field_name="_", method="filter_playable") tag = TAG_FILTER @@ -47,7 +69,9 @@ class ArtistFilter( class TrackFilter( - audio_filters.IncludeChannelsFilterSet, moderation_filters.HiddenContentFilterSet + ChannelFilterSet, + audio_filters.IncludeChannelsFilterSet, + moderation_filters.HiddenContentFilterSet, ): q = fields.SearchFilter( search_fields=["title", "album__title", "artist__name"], @@ -74,6 +98,7 @@ class TrackFilter( } hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG["TRACK"] include_channels_field = "artist__channel" + channel_filter_field = "track" def filter_playable(self, queryset, name, value): actor = utils.get_actor_from_request(self.request) @@ -127,7 +152,9 @@ class UploadFilter(audio_filters.IncludeChannelsFilterSet): class AlbumFilter( - audio_filters.IncludeChannelsFilterSet, moderation_filters.HiddenContentFilterSet + ChannelFilterSet, + audio_filters.IncludeChannelsFilterSet, + moderation_filters.HiddenContentFilterSet, ): playable = filters.BooleanFilter(field_name="_", method="filter_playable") q = fields.SearchFilter( @@ -144,6 +171,7 @@ class AlbumFilter( fields = ["playable", "q", "artist", "scope", "mbid"] hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG["ALBUM"] include_channels_field = "artist__channel" + channel_filter_field = "track__album" def filter_playable(self, queryset, name, value): actor = utils.get_actor_from_request(self.request) diff --git a/api/tests/music/test_filters.py b/api/tests/music/test_filters.py index 7ce7e16a0..ea4543ddb 100644 --- a/api/tests/music/test_filters.py +++ b/api/tests/music/test_filters.py @@ -110,3 +110,35 @@ def test_track_filter_tag_multiple( ) assert filterset.qs == [tagged] + + +def test_channel_filter_track(factories, queryset_equal_list, mocker, anonymous_user): + channel = factories["audio.Channel"]() + upload = factories["music.Upload"]( + library=channel.library, playable=True, track__artist=channel.artist + ) + factories["music.Track"]() + qs = upload.track.__class__.objects.all() + filterset = filters.TrackFilter( + {"channel": channel.uuid, "include_channels": "true"}, + request=mocker.Mock(user=anonymous_user, actor=None), + queryset=qs, + ) + + assert filterset.qs == [upload.track] + + +def test_channel_filter_album(factories, queryset_equal_list, mocker, anonymous_user): + channel = factories["audio.Channel"]() + upload = factories["music.Upload"]( + library=channel.library, playable=True, track__artist=channel.artist + ) + factories["music.Album"]() + qs = upload.track.album.__class__.objects.all() + filterset = filters.AlbumFilter( + {"channel": channel.uuid, "include_channels": "true"}, + request=mocker.Mock(user=anonymous_user, actor=None), + queryset=qs, + ) + + assert filterset.qs == [upload.track.album]