Serializers for paginated collections
This commit is contained in:
parent
4ce9f9bf08
commit
393110a7f0
|
@ -30,6 +30,9 @@ FUNKWHALE_HOSTNAME = urlsplit(FUNKWHALE_URL).netloc
|
|||
|
||||
FEDERATION_ENABLED = env.bool('FEDERATION_ENABLED', default=True)
|
||||
FEDERATION_HOSTNAME = env('FEDERATION_HOSTNAME', default=FUNKWHALE_HOSTNAME)
|
||||
FEDERATION_COLLECTION_PAGE_SIZE = env.int(
|
||||
'FEDERATION_COLLECTION_PAGE_SIZE', default=50
|
||||
)
|
||||
FEDERATION_MUSIC_NEEDS_APPROVAL = env.bool(
|
||||
'FEDERATION_MUSIC_NEEDS_APPROVAL', default=True
|
||||
)
|
||||
|
|
|
@ -2,10 +2,13 @@ import urllib.parse
|
|||
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
from django.core.paginator import Paginator
|
||||
|
||||
from rest_framework import serializers
|
||||
from dynamic_preferences.registries import global_preferences_registry
|
||||
|
||||
from funkwhale_api.common.utils import set_query_parameter
|
||||
|
||||
from . import activity
|
||||
from . import models
|
||||
from . import utils
|
||||
|
@ -199,3 +202,66 @@ OBJECT_SERIALIZERS = {
|
|||
t: ObjectSerializer
|
||||
for t in activity.OBJECT_TYPES
|
||||
}
|
||||
|
||||
|
||||
class PaginatedCollectionSerializer(serializers.Serializer):
|
||||
|
||||
def to_representation(self, conf):
|
||||
paginator = Paginator(
|
||||
conf['items'],
|
||||
conf.get('page_size', 20)
|
||||
)
|
||||
first = set_query_parameter(conf['id'], page=1)
|
||||
current = first
|
||||
last = set_query_parameter(conf['id'], page=paginator.num_pages)
|
||||
d = {
|
||||
'id': conf['id'],
|
||||
'actor': conf['actor'].url,
|
||||
'totalItems': paginator.count,
|
||||
'type': 'Collection',
|
||||
'current': current,
|
||||
'first': first,
|
||||
'last': last,
|
||||
}
|
||||
if self.context.get('include_ap_context', True):
|
||||
d['@context'] = AP_CONTEXT
|
||||
return d
|
||||
|
||||
|
||||
class CollectionPageSerializer(serializers.Serializer):
|
||||
|
||||
def to_representation(self, conf):
|
||||
page = conf['page']
|
||||
first = set_query_parameter(conf['id'], page=1)
|
||||
last = set_query_parameter(conf['id'], page=page.paginator.num_pages)
|
||||
id = set_query_parameter(conf['id'], page=page.number)
|
||||
d = {
|
||||
'id': id,
|
||||
'partOf': conf['id'],
|
||||
'actor': conf['actor'].url,
|
||||
'totalItems': page.paginator.count,
|
||||
'type': 'CollectionPage',
|
||||
'first': first,
|
||||
'last': last,
|
||||
'items': [
|
||||
conf['item_serializer'](
|
||||
i,
|
||||
context={
|
||||
'actor': conf['actor'],
|
||||
'include_ap_context': False}
|
||||
).data
|
||||
for i in page.object_list
|
||||
]
|
||||
}
|
||||
|
||||
if page.has_previous():
|
||||
d['prev'] = set_query_parameter(
|
||||
conf['id'], page=page.previous_page_number())
|
||||
|
||||
if page.has_previous():
|
||||
d['next'] = set_query_parameter(
|
||||
conf['id'], page=page.next_page_number())
|
||||
|
||||
if self.context.get('include_ap_context', True):
|
||||
d['@context'] = AP_CONTEXT
|
||||
return d
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from django.urls import reverse
|
||||
from django.core.paginator import Paginator
|
||||
|
||||
from funkwhale_api.federation import keys
|
||||
from funkwhale_api.federation import models
|
||||
from funkwhale_api.federation import serializers
|
||||
from funkwhale_api.music.serializers import AudioSerializer
|
||||
|
||||
|
||||
def test_actor_serializer_from_ap(db):
|
||||
|
@ -163,3 +165,73 @@ def test_follow_serializer_to_ap(factories):
|
|||
}
|
||||
|
||||
assert serializer.data == expected
|
||||
|
||||
|
||||
def test_paginated_collection_serializer(factories):
|
||||
tfs = factories['music.TrackFile'].create_batch(size=5)
|
||||
actor = factories['federation.Actor'](local=True)
|
||||
|
||||
conf = {
|
||||
'id': 'https://test.federation/test',
|
||||
'items': tfs,
|
||||
'item_serializer': AudioSerializer,
|
||||
'actor': actor,
|
||||
'page_size': 2,
|
||||
}
|
||||
expected = {
|
||||
'@context': [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1',
|
||||
{},
|
||||
],
|
||||
'type': 'Collection',
|
||||
'id': conf['id'],
|
||||
'actor': actor.url,
|
||||
'totalItems': len(tfs),
|
||||
'current': conf['id'] + '?page=1',
|
||||
'last': conf['id'] + '?page=3',
|
||||
'first': conf['id'] + '?page=1',
|
||||
}
|
||||
|
||||
serializer = serializers.PaginatedCollectionSerializer(conf)
|
||||
|
||||
assert serializer.data == expected
|
||||
|
||||
|
||||
def test_collection_page_serializer(factories):
|
||||
tfs = factories['music.TrackFile'].create_batch(size=5)
|
||||
actor = factories['federation.Actor'](local=True)
|
||||
|
||||
conf = {
|
||||
'id': 'https://test.federation/test',
|
||||
'item_serializer': AudioSerializer,
|
||||
'actor': actor,
|
||||
'page': Paginator(tfs, 2).page(2),
|
||||
}
|
||||
expected = {
|
||||
'@context': [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1',
|
||||
{},
|
||||
],
|
||||
'type': 'CollectionPage',
|
||||
'id': conf['id'] + '?page=2',
|
||||
'actor': actor.url,
|
||||
'totalItems': len(tfs),
|
||||
'partOf': conf['id'],
|
||||
'prev': conf['id'] + '?page=1',
|
||||
'next': conf['id'] + '?page=3',
|
||||
'first': conf['id'] + '?page=1',
|
||||
'last': conf['id'] + '?page=3',
|
||||
'items': [
|
||||
conf['item_serializer'](
|
||||
i,
|
||||
context={'actor': actor, 'include_ap_context': False}
|
||||
).data
|
||||
for i in conf['page'].object_list
|
||||
]
|
||||
}
|
||||
|
||||
serializer = serializers.CollectionPageSerializer(conf)
|
||||
|
||||
assert serializer.data == expected
|
||||
|
|
Loading…
Reference in New Issue