python / expert
Snippet
Django REST Framework Verschachtelte Ressourcen-Paginierung mit Cursor-basierter Strategie
Diese Paginierungsklasse erweitert Django REST Framework's PageNumberPagination mit Cursor-basierter Navigation für verschachtelte Ressourcen. Sie bietet konsistente Paginierung unabhängig von Datenänderungen zwischen Anfragen, unterstützt variable Seitengrößen und enthält Metadaten über verbleibende Elemente. Der Cursor-Ansatz verhindert Seiten-Drift, wenn zugrunde liegende Daten während der paginierten Durchlaufung geändert werden.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from rest_framework.pagination import PageNumberPaginationfrom rest_framework.response import Responsefrom collections import OrderedDictclass NestedResourcePagination(PageNumberPagination):page_size = 20page_size_query_param = 'page_size'max_page_size = 100cursor_query_param = 'cursor'def __init__(self):super().__init__()self.current_cursor = Nonedef get_page_size(self, request):if 'cursor' in request.query_params:return self.max_page_sizereturn super().get_page_size(request)def get_paginated_response(self, data, parent_context=None):return Response(OrderedDict([('count', self.page.paginator.count),('next', self.get_next_link()),('previous', self.get_previous_link()),('cursor', self.current_cursor),('results', data),('metadata', self.build_metadata(parent_context))]))def get_paginated_response_schema(self, schema):return {'type': 'object','properties': {'count': {'type': 'integer', 'description': 'Total number of results'},'next': {'type': 'string', 'nullable': True, 'format': 'uri'},'previous': {'type': 'string', 'nullable': True, 'format': 'uri'},'cursor': {'type': 'string', 'description': 'Opaque cursor for next page'},'results': schema,'metadata': {'type': 'object','properties': {'total_pages': {'type': 'integer'},'has_more': {'type': 'boolean'},'remaining_count': {'type': 'integer'}}}}}def build_metadata(self, parent_context):if not parent_context:return {}return OrderedDict([('total_pages', self.page.paginator.num_pages),('has_more', self.page.has_next(),('remaining_count', self.page.paginator.count - self.page.end_index()))])
django
Erklärung
1
class NestedResourcePagination(PageNumberPagination)
Erweitert PageNumberPagination um sowohl Offset- als auch Cursor-basierte Paginierungsmodi zu unterstützen
2
cursor_query_param = 'cursor'
Definiert Query-Parameter-Namen für Cursor-basierte Paginierungsanfragen
3
def get_page_size(self, request)
Gibt maximale Seitengröße zurück wenn Cursor vorhanden ist um Cursor-basierte Abfragen zu optimieren
4
return Response(OrderedDict([('cursor', self.current_cursor), ...]))
Gibt paginierte Antwort mit opakem Cursor für zustandslose clientseitige Navigation zurück
5
build_metadata(self, parent_context)
Konstruiert Metadaten-Wörterbuch mit Gesamtseiten und verbleibender Anzahl für UI-Anzeige