
+ Import
+ Import batches
+
diff --git a/api/config/settings/common.py b/api/config/settings/common.py
index 3f7cc7503..6a2299bb4 100644
--- a/api/config/settings/common.py
+++ b/api/config/settings/common.py
@@ -54,6 +54,7 @@ THIRD_PARTY_APPS = (
'rest_auth.registration',
'mptt',
'dynamic_preferences',
+ 'django_filters',
)
# Apps specific for this project go here.
@@ -298,7 +299,7 @@ REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
- 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
+ 'DEFAULT_PAGINATION_CLASS': 'funkwhale_api.common.pagination.FunkwhalePagination',
'PAGE_SIZE': 25,
'DEFAULT_AUTHENTICATION_CLASSES': (
@@ -309,6 +310,7 @@ REST_FRAMEWORK = {
),
'DEFAULT_FILTER_BACKENDS': (
'rest_framework.filters.OrderingFilter',
+ 'django_filters.rest_framework.DjangoFilterBackend',
)
}
diff --git a/api/funkwhale_api/common/pagination.py b/api/funkwhale_api/common/pagination.py
new file mode 100644
index 000000000..224c470dc
--- /dev/null
+++ b/api/funkwhale_api/common/pagination.py
@@ -0,0 +1,6 @@
+from rest_framework.pagination import PageNumberPagination
+
+
+class FunkwhalePagination(PageNumberPagination):
+ page_size_query_param = 'page_size'
+ max_page_size = 25
diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py
new file mode 100644
index 000000000..ba3fa453d
--- /dev/null
+++ b/api/funkwhale_api/music/filters.py
@@ -0,0 +1,12 @@
+import django_filters
+
+from . import models
+
+
+class ArtistFilter(django_filters.FilterSet):
+
+ class Meta:
+ model = models.Artist
+ fields = {
+ 'name': ['exact', 'iexact', 'startswith']
+ }
diff --git a/api/funkwhale_api/music/tests/test_api.py b/api/funkwhale_api/music/tests/test_api.py
index 21a567084..b7c25424f 100644
--- a/api/funkwhale_api/music/tests/test_api.py
+++ b/api/funkwhale_api/music/tests/test_api.py
@@ -182,6 +182,21 @@ class TestAPI(TMPDirTestCaseMixin, TestCase):
self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8')))
+ def test_can_search_artist_by_name_start(self):
+ artist1 = factories.ArtistFactory(name='alpha')
+ artist2 = factories.ArtistFactory(name='beta')
+ results = {
+ 'next': None,
+ 'previous': None,
+ 'count': 1,
+ 'results': [serializers.ArtistSerializerNested(artist1).data]
+ }
+ expected = json.dumps(results)
+ url = self.reverse('api:v1:artists-list')
+ response = self.client.get(url, {'name__startswith': 'a'})
+
+ self.assertJSONEqual(expected, json.loads(response.content.decode('utf-8')))
+
def test_can_search_tracks(self):
artist1 = models.Artist.objects.create(name='Test1')
artist2 = models.Artist.objects.create(name='Test2')
diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py
index 983192552..d149b5d1b 100644
--- a/api/funkwhale_api/music/views.py
+++ b/api/funkwhale_api/music/views.py
@@ -21,8 +21,10 @@ from taggit.models import Tag
from . import models
from . import serializers
from . import importers
+from . import filters
from . import utils
+
class SearchMixin(object):
search_fields = []
@@ -52,7 +54,8 @@ class ArtistViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
serializer_class = serializers.ArtistSerializerNested
permission_classes = [ConditionalAuthentication]
search_fields = ['name']
- ordering_fields = ('creation_date',)
+ ordering_fields = ('creation_date', 'name')
+ filter_class = filters.ArtistFilter
class AlbumViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
diff --git a/api/requirements/base.txt b/api/requirements/base.txt
index e7bc870cf..3a11afadf 100644
--- a/api/requirements/base.txt
+++ b/api/requirements/base.txt
@@ -45,6 +45,7 @@ django-taggit==0.22.1
persisting-theory==0.2.1
django-versatileimagefield==1.7.1
django-cachalot==1.5.0
+django-filter==1.1
django-rest-auth==0.9.1
beautifulsoup4==4.6.0
Markdown==2.6.8
diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue
index 72b7d7ef9..423c9d12f 100644
--- a/front/src/components/audio/Player.vue
+++ b/front/src/components/audio/Player.vue
@@ -7,14 +7,14 @@