mirror of
https://code.eliotberriot.com/funkwhale/funkwhale.git
synced 2025-10-06 04:19:56 +02:00
Added a new ?related=obj_id filter for artists, albums and tracks, based on tags
This commit is contained in:
parent
ae7819048e
commit
d50cce36e2
5 changed files with 87 additions and 0 deletions
|
@ -9,6 +9,7 @@ from funkwhale_api.common import fields
|
|||
from funkwhale_api.common import filters as common_filters
|
||||
from funkwhale_api.common import search
|
||||
from funkwhale_api.moderation import filters as moderation_filters
|
||||
from funkwhale_api.tags import filters as tags_filters
|
||||
|
||||
from . import models
|
||||
from . import utils
|
||||
|
@ -24,6 +25,28 @@ def filter_tags(queryset, name, value):
|
|||
TAG_FILTER = common_filters.MultipleQueryFilter(method=filter_tags)
|
||||
|
||||
|
||||
class RelatedFilterSet(filters.FilterSet):
|
||||
related_type = int
|
||||
related_field = "pk"
|
||||
related = filters.CharFilter(field_name="_", method="filter_related")
|
||||
|
||||
def filter_related(self, queryset, name, value):
|
||||
if not value:
|
||||
return queryset.none()
|
||||
try:
|
||||
pk = self.related_type(value)
|
||||
except (TypeError, ValueError):
|
||||
return queryset.none()
|
||||
|
||||
try:
|
||||
obj = queryset.model.objects.get(**{self.related_field: pk})
|
||||
except queryset.model.DoesNotExist:
|
||||
return queryset.none()
|
||||
|
||||
queryset = queryset.exclude(pk=obj.pk)
|
||||
return tags_filters.get_by_similar_tags(queryset, obj.get_tags())
|
||||
|
||||
|
||||
class ChannelFilterSet(filters.FilterSet):
|
||||
|
||||
channel = filters.CharFilter(field_name="_", method="filter_channel")
|
||||
|
@ -70,6 +93,7 @@ class LibraryFilterSet(filters.FilterSet):
|
|||
|
||||
|
||||
class ArtistFilter(
|
||||
RelatedFilterSet,
|
||||
LibraryFilterSet,
|
||||
audio_filters.IncludeChannelsFilterSet,
|
||||
moderation_filters.HiddenContentFilterSet,
|
||||
|
@ -88,6 +112,7 @@ class ArtistFilter(
|
|||
("creation_date", "creation_date"),
|
||||
("modification_date", "modification_date"),
|
||||
("?", "random"),
|
||||
("tag_matches", "related"),
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -109,6 +134,7 @@ class ArtistFilter(
|
|||
|
||||
|
||||
class TrackFilter(
|
||||
RelatedFilterSet,
|
||||
ChannelFilterSet,
|
||||
LibraryFilterSet,
|
||||
audio_filters.IncludeChannelsFilterSet,
|
||||
|
@ -140,6 +166,7 @@ class TrackFilter(
|
|||
("artist__name", "artist__name"),
|
||||
("artist__modification_date", "artist__modification_date"),
|
||||
("?", "random"),
|
||||
("tag_matches", "related"),
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -217,6 +244,7 @@ class UploadFilter(audio_filters.IncludeChannelsFilterSet):
|
|||
|
||||
|
||||
class AlbumFilter(
|
||||
RelatedFilterSet,
|
||||
ChannelFilterSet,
|
||||
LibraryFilterSet,
|
||||
audio_filters.IncludeChannelsFilterSet,
|
||||
|
@ -239,6 +267,7 @@ class AlbumFilter(
|
|||
("title", "title"),
|
||||
("artist__modification_date", "artist__modification_date"),
|
||||
("?", "random"),
|
||||
("tag_matches", "related"),
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from django.db import models as dj_models
|
||||
|
||||
import django_filters
|
||||
from django_filters import rest_framework as filters
|
||||
|
||||
|
@ -19,3 +21,19 @@ class TagFilter(filters.FilterSet):
|
|||
class Meta:
|
||||
model = models.Tag
|
||||
fields = {"q": ["exact"], "name": ["exact", "startswith"]}
|
||||
|
||||
|
||||
def get_by_similar_tags(qs, tags):
|
||||
"""
|
||||
Return a queryset of obects with at least one matching tag.
|
||||
Annotate the queryset so you can order later by number of matches.
|
||||
"""
|
||||
qs = qs.filter(tagged_items__tag__name__in=tags).annotate(
|
||||
tag_matches=dj_models.Count(
|
||||
dj_models.Case(
|
||||
dj_models.When(tagged_items__tag__name__in=tags, then=1),
|
||||
output_field=dj_models.IntegerField(),
|
||||
)
|
||||
)
|
||||
)
|
||||
return qs.distinct()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue