Serializers for paginated collections

This commit is contained in:
Eliot Berriot 2018-04-06 17:58:43 +02:00
parent 4ce9f9bf08
commit 393110a7f0
No known key found for this signature in database
GPG Key ID: DD6965E2476E5C27
3 changed files with 141 additions and 0 deletions

View File

@ -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
)

View File

@ -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

View File

@ -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