From afc8f22516921e9ed320ccea6da245d730beaa27 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Mon, 21 Oct 2019 09:25:36 +0200 Subject: [PATCH] Fix tag exclusion in custom radios (#950) --- api/funkwhale_api/radios/filters.py | 6 +++-- api/tests/radios/test_radios.py | 38 +++++++++++++++++++++++++++++ changes/changelog.d/950.bugfix | 1 + 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 changes/changelog.d/950.bugfix diff --git a/api/funkwhale_api/radios/filters.py b/api/funkwhale_api/radios/filters.py index a92dbae88..f3abe22e0 100644 --- a/api/funkwhale_api/radios/filters.py +++ b/api/funkwhale_api/radios/filters.py @@ -30,7 +30,7 @@ def run(filters, **kwargs): if final_query: candidates = candidates.filter(final_query) - return candidates.order_by("pk") + return candidates.order_by("pk").distinct() def validate(filter_config): @@ -100,7 +100,9 @@ class GroupFilter(RadioFilter): conf = collections.ChainMap(filter_config, kwargs) query = f.get_query(candidates, **conf) if filter_config.get("not", False): - query = ~query + # query = ~query *should* work but it doesn't (see #950) + # The line below generate a proper subquery + query = ~Q(pk__in=candidates.filter(query).values_list("pk", flat=True)) if not final_query: final_query = query diff --git a/api/tests/radios/test_radios.py b/api/tests/radios/test_radios.py index 040217aac..2aa60c36a 100644 --- a/api/tests/radios/test_radios.py +++ b/api/tests/radios/test_radios.py @@ -282,3 +282,41 @@ def test_session_radio_get_queryset_ignore_filtered_track_album_artist( radio.start_session(user=cf.user) assert radio.get_queryset() == [valid_track] + + +def test_get_choices_for_custom_radio_exclude_artist(factories): + included_artist = factories["music.Artist"]() + excluded_artist = factories["music.Artist"]() + included_uploads = factories["music.Upload"].create_batch( + 5, track__artist=included_artist + ) + factories["music.Upload"].create_batch(5, track__artist=excluded_artist) + + session = factories["radios.CustomRadioSession"]( + custom_radio__config=[ + {"type": "artist", "ids": [included_artist.pk]}, + {"type": "artist", "ids": [excluded_artist.pk], "not": True}, + ] + ) + choices = session.radio.get_choices(filter_playable=False) + + expected = [u.track.pk for u in included_uploads] + assert list(choices.values_list("id", flat=True)) == expected + + +def test_get_choices_for_custom_radio_exclude_tag(factories): + included_uploads = factories["music.Upload"].create_batch( + 5, track__set_tags=["rap"] + ) + factories["music.Upload"].create_batch(5, track__set_tags=["rock", "rap"]) + + session = factories["radios.CustomRadioSession"]( + custom_radio__config=[ + {"type": "tag", "names": ["rap"]}, + {"type": "tag", "names": ["rock"], "not": True}, + ] + ) + choices = session.radio.get_choices(filter_playable=False) + + expected = [u.track.pk for u in included_uploads] + assert list(choices.values_list("id", flat=True)) == expected diff --git a/changes/changelog.d/950.bugfix b/changes/changelog.d/950.bugfix new file mode 100644 index 000000000..c1195739e --- /dev/null +++ b/changes/changelog.d/950.bugfix @@ -0,0 +1 @@ +Fix tag exclusion in custom radios (#950)