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_ENABLED = env.bool('FEDERATION_ENABLED', default=True)
|
||||||
FEDERATION_HOSTNAME = env('FEDERATION_HOSTNAME', default=FUNKWHALE_HOSTNAME)
|
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 = env.bool(
|
||||||
'FEDERATION_MUSIC_NEEDS_APPROVAL', default=True
|
'FEDERATION_MUSIC_NEEDS_APPROVAL', default=True
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,10 +2,13 @@ import urllib.parse
|
||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from dynamic_preferences.registries import global_preferences_registry
|
from dynamic_preferences.registries import global_preferences_registry
|
||||||
|
|
||||||
|
from funkwhale_api.common.utils import set_query_parameter
|
||||||
|
|
||||||
from . import activity
|
from . import activity
|
||||||
from . import models
|
from . import models
|
||||||
from . import utils
|
from . import utils
|
||||||
|
@ -199,3 +202,66 @@ OBJECT_SERIALIZERS = {
|
||||||
t: ObjectSerializer
|
t: ObjectSerializer
|
||||||
for t in activity.OBJECT_TYPES
|
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.urls import reverse
|
||||||
|
from django.core.paginator import Paginator
|
||||||
|
|
||||||
from funkwhale_api.federation import keys
|
from funkwhale_api.federation import keys
|
||||||
from funkwhale_api.federation import models
|
from funkwhale_api.federation import models
|
||||||
from funkwhale_api.federation import serializers
|
from funkwhale_api.federation import serializers
|
||||||
|
from funkwhale_api.music.serializers import AudioSerializer
|
||||||
|
|
||||||
|
|
||||||
def test_actor_serializer_from_ap(db):
|
def test_actor_serializer_from_ap(db):
|
||||||
|
@ -163,3 +165,73 @@ def test_follow_serializer_to_ap(factories):
|
||||||
}
|
}
|
||||||
|
|
||||||
assert serializer.data == expected
|
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