Merge branch '114-exclude-empty-albums' into 'develop'
Fix #114: can now filter artists and albums with no listenable tracks Closes #114 See merge request funkwhale/funkwhale!83
This commit is contained in:
commit
c70ab72bc0
|
@ -1,12 +1,36 @@
|
||||||
import django_filters
|
from django.db.models import Count
|
||||||
|
|
||||||
|
from django_filters import rest_framework as filters
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
class ArtistFilter(django_filters.FilterSet):
|
class ListenableMixin(filters.FilterSet):
|
||||||
|
listenable = filters.BooleanFilter(name='_', method='filter_listenable')
|
||||||
|
|
||||||
|
def filter_listenable(self, queryset, name, value):
|
||||||
|
queryset = queryset.annotate(
|
||||||
|
files_count=Count('tracks__files')
|
||||||
|
)
|
||||||
|
if value:
|
||||||
|
return queryset.filter(files_count__gt=0)
|
||||||
|
else:
|
||||||
|
return queryset.filter(files_count=0)
|
||||||
|
|
||||||
|
|
||||||
|
class ArtistFilter(ListenableMixin):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Artist
|
model = models.Artist
|
||||||
fields = {
|
fields = {
|
||||||
'name': ['exact', 'iexact', 'startswith', 'icontains']
|
'name': ['exact', 'iexact', 'startswith', 'icontains'],
|
||||||
|
'listenable': 'exact',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AlbumFilter(ListenableMixin):
|
||||||
|
listenable = filters.BooleanFilter(name='_', method='filter_listenable')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = models.Album
|
||||||
|
fields = ['listenable']
|
||||||
|
|
|
@ -54,6 +54,7 @@ class TagViewSetMixin(object):
|
||||||
queryset = queryset.filter(tags__pk=tag)
|
queryset = queryset.filter(tags__pk=tag)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class ArtistViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
|
class ArtistViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
|
||||||
queryset = (
|
queryset = (
|
||||||
models.Artist.objects.all()
|
models.Artist.objects.all()
|
||||||
|
@ -67,6 +68,7 @@ class ArtistViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
|
||||||
filter_class = filters.ArtistFilter
|
filter_class = filters.ArtistFilter
|
||||||
ordering_fields = ('id', 'name', 'creation_date')
|
ordering_fields = ('id', 'name', 'creation_date')
|
||||||
|
|
||||||
|
|
||||||
class AlbumViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
|
class AlbumViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
|
||||||
queryset = (
|
queryset = (
|
||||||
models.Album.objects.all()
|
models.Album.objects.all()
|
||||||
|
@ -78,6 +80,7 @@ class AlbumViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
|
||||||
permission_classes = [ConditionalAuthentication]
|
permission_classes = [ConditionalAuthentication]
|
||||||
search_fields = ['title__unaccent']
|
search_fields = ['title__unaccent']
|
||||||
ordering_fields = ('creation_date',)
|
ordering_fields = ('creation_date',)
|
||||||
|
filter_class = filters.AlbumFilter
|
||||||
|
|
||||||
|
|
||||||
class ImportBatchViewSet(
|
class ImportBatchViewSet(
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pytest
|
||||||
from django.core.cache import cache as django_cache
|
from django.core.cache import cache as django_cache
|
||||||
from dynamic_preferences.registries import global_preferences_registry
|
from dynamic_preferences.registries import global_preferences_registry
|
||||||
from rest_framework.test import APIClient
|
from rest_framework.test import APIClient
|
||||||
|
from rest_framework.test import APIRequestFactory
|
||||||
|
|
||||||
from funkwhale_api.activity import record
|
from funkwhale_api.activity import record
|
||||||
from funkwhale_api.taskapp import celery
|
from funkwhale_api.taskapp import celery
|
||||||
|
@ -84,6 +85,11 @@ def superuser_client(db, factories, client):
|
||||||
delattr(client, 'user')
|
delattr(client, 'user')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def api_request():
|
||||||
|
return APIRequestFactory()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def activity_registry():
|
def activity_registry():
|
||||||
r = record.registry
|
r = record.registry
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from funkwhale_api.music import views
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('param,expected', [
|
||||||
|
('true', 'full'),
|
||||||
|
('false', 'empty'),
|
||||||
|
])
|
||||||
|
def test_artist_view_filter_listenable(
|
||||||
|
param, expected, factories, api_request):
|
||||||
|
artists = {
|
||||||
|
'empty': factories['music.Artist'](),
|
||||||
|
'full': factories['music.TrackFile']().track.artist,
|
||||||
|
}
|
||||||
|
|
||||||
|
request = api_request.get('/', {'listenable': param})
|
||||||
|
view = views.ArtistViewSet()
|
||||||
|
view.action_map = {'get': 'list'}
|
||||||
|
expected = [artists[expected]]
|
||||||
|
view.request = view.initialize_request(request)
|
||||||
|
queryset = view.filter_queryset(view.get_queryset())
|
||||||
|
|
||||||
|
assert list(queryset) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('param,expected', [
|
||||||
|
('true', 'full'),
|
||||||
|
('false', 'empty'),
|
||||||
|
])
|
||||||
|
def test_album_view_filter_listenable(
|
||||||
|
param, expected, factories, api_request):
|
||||||
|
artists = {
|
||||||
|
'empty': factories['music.Album'](),
|
||||||
|
'full': factories['music.TrackFile']().track.album,
|
||||||
|
}
|
||||||
|
|
||||||
|
request = api_request.get('/', {'listenable': param})
|
||||||
|
view = views.AlbumViewSet()
|
||||||
|
view.action_map = {'get': 'list'}
|
||||||
|
expected = [artists[expected]]
|
||||||
|
view.request = view.initialize_request(request)
|
||||||
|
queryset = view.filter_queryset(view.get_queryset())
|
||||||
|
|
||||||
|
assert list(queryset) == expected
|
|
@ -0,0 +1 @@
|
||||||
|
Can now filter artists and albums with no listenable tracks (#114)
|
|
@ -129,7 +129,8 @@ export default {
|
||||||
page: this.page,
|
page: this.page,
|
||||||
page_size: this.paginateBy,
|
page_size: this.paginateBy,
|
||||||
name__icontains: this.query,
|
name__icontains: this.query,
|
||||||
ordering: this.getOrderingAsString()
|
ordering: this.getOrderingAsString(),
|
||||||
|
listenable: 'true'
|
||||||
}
|
}
|
||||||
logger.default.debug('Fetching artists')
|
logger.default.debug('Fetching artists')
|
||||||
axios.get(url, {params: params}).then((response) => {
|
axios.get(url, {params: params}).then((response) => {
|
||||||
|
|
Loading…
Reference in New Issue