Fix(radios): search filters incoherent behaviour

This commit is contained in:
Marcos Peña 2022-07-21 17:20:31 +02:00
parent 209e118882
commit 0551af5042
3 changed files with 75 additions and 7 deletions

View File

@ -2,7 +2,7 @@ import collections
import persisting_theory
from django.core.exceptions import ValidationError
from django.db.models import Q
from django.db.models import Q, functions
from django.urls import reverse_lazy
from funkwhale_api.music import models
@ -132,9 +132,13 @@ class ArtistFilter(RadioFilter):
"name": "ids",
"type": "list",
"subtype": "number",
"autocomplete": reverse_lazy("api:v1:artists-list"),
"autocomplete": reverse_lazy("api:v1:search"),
"autocomplete_qs": "q={query}",
"autocomplete_fields": {"name": "name", "value": "id"},
"autocomplete_fields": {
"remoteValues": "artists",
"name": "name",
"value": "id",
},
"label": "Artist",
"placeholder": "Select artists",
}
@ -145,7 +149,8 @@ class ArtistFilter(RadioFilter):
filter_config["ids"] = sorted(filter_config["ids"])
names = (
models.Artist.objects.filter(pk__in=filter_config["ids"])
.order_by("id")
.annotate(__size=functions.Length("name"))
.order_by("__size", "id")
.values_list("name", flat=True)
)
filter_config["names"] = list(names)
@ -176,13 +181,13 @@ class TagFilter(RadioFilter):
"name": "names",
"type": "list",
"subtype": "string",
"autocomplete": reverse_lazy("api:v1:tags-list"),
"autocomplete": reverse_lazy("api:v1:search"),
"autocomplete_fields": {
"remoteValues": "results",
"remoteValues": "tags",
"name": "name",
"value": "name",
},
"autocomplete_qs": "q={query}&ordering=length",
"autocomplete_qs": "q={query}",
"label": "Tags",
"placeholder": "Select tags",
}
@ -196,3 +201,28 @@ class TagFilter(RadioFilter):
| Q(artist__tagged_items__tag__name__in=names)
| Q(album__tagged_items__tag__name__in=names)
)
def clean_config(self, filter_config):
filter_config = super().clean_config(filter_config)
filter_config["names"] = sorted(filter_config["names"])
names = (
models.tags_models.Tag.objects.filter(name__in=filter_config["names"])
.annotate(__size=functions.Length("name"))
.order_by("__size", "pk")
.values_list("name", flat=True)
)
filter_config["names"] = list(names)
return filter_config
def validate(self, config):
super().validate(config)
try:
names = models.tags_models.Tag.objects.filter(
name__in=config["names"]
).values_list("name", flat=True)
diff = set(config["names"]) - set(names)
assert len(diff) == 0
except KeyError:
raise ValidationError("You must provide a name")
except AssertionError:
raise ValidationError('No tag matching names "{}"'.format(diff))

View File

@ -0,0 +1,37 @@
from funkwhale_api.radios import filters
def test_clean_config_artist_name_sorting(factories):
artist3 = factories["music.Artist"](name="The Green Eyes")
artist2 = factories["music.Artist"](name="The Green Eyed Machine")
artist1 = factories["music.Artist"](name="The Green Seed")
factories["music.Artist"]()
filter_config = {"type": "artist", "ids": [artist3.pk, artist1.pk, artist2.pk]}
artist_filter = filters.ArtistFilter()
config = artist_filter.clean_config(filter_config)
# list of names whose artists have been sorted by name then by id
sorted_names = [
a.name
for a in list(
sorted([artist2, artist1, artist3], key=lambda x: (len(x.name), x.id))
)
]
assert config["names"] == sorted_names
def test_clean_config_tag_name_sorting(factories):
tag3 = factories["tags.Tag"](name="Rock")
tag2 = factories["tags.Tag"](name="Classic")
tag1 = factories["tags.Tag"](name="Punk")
factories["tags.Tag"]()
filter_config = {"type": "tag", "names": [tag3.name, tag1.name, tag2.name]}
tag_filter = filters.TagFilter()
config = tag_filter.clean_config(filter_config)
# list of names whose tags have been sorted by name then by id
sorted_names = [
a.name
for a in list(sorted([tag2, tag1, tag3], key=lambda x: (len(x.name), x.id)))
]
assert config["names"] == sorted_names

View File

@ -0,0 +1 @@
Fixed search behaviour in radio builder's filters (#733)