Coverage for api/utils/pagination.py: 100%

22 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 06:14 +0000

1from rest_framework.pagination import PageNumberPagination 

2from rest_framework.response import Response 

3 

4 

5class StandardPagination(PageNumberPagination): 

6 page_size_query_param = "page_size" 

7 page_query_param = "page" 

8 

9 result_count: int | None 

10 page_count: int | None 

11 page: int 

12 warnings: list[dict] 

13 

14 def __init__(self, *args, **kwargs): 

15 super().__init__(*args, **kwargs) 

16 self.result_count = None # populated later 

17 self.page_count = None # populated later 

18 self.page = 1 # default, gets updated when necessary 

19 self.warnings = [] # populated later as needed 

20 

21 def get_paginated_response(self, data): 

22 response = { 

23 "result_count": self.result_count, 

24 "page_count": self.page_count, 

25 "page_size": self.page_size, 

26 "page": self.page, 

27 "results": data, 

28 } 

29 return Response( 

30 ( 

31 { 

32 # Put ``warnings`` first so it is as visible as possible. 

33 "warnings": list(self.warnings), 

34 } 

35 if self.warnings 

36 else {} 

37 ) 

38 | response 

39 ) 

40 

41 def get_paginated_response_schema(self, schema): 

42 """ 

43 Get the schema of the paginated response, used by `drf-spectacular` to 

44 generate the documentation of the paginated search results response. 

45 """ 

46 

47 field_descriptions = { 

48 "result_count": ( 

49 "The total number of items returned by search result.", 

50 10000, 

51 ), 

52 "page_count": ("The total number of pages returned by search result.", 20), 

53 "page_size": ("The number of items per page.", 20), 

54 "page": ("The current page number returned in the response.", 1), 

55 } 

56 

57 properties = { 

58 field: { 

59 "type": "integer", 

60 "description": description, 

61 "example": example, 

62 } 

63 for field, (description, example) in field_descriptions.items() 

64 } | { 

65 "results": schema, 

66 "warnings": { 

67 "type": "array", 

68 "items": { 

69 "type": "object", 

70 }, 

71 "description": ( 

72 "Warnings pertinent to the request. " 

73 "If there are no warnings, this property will not be present on the response. " 

74 "Warnings are non-critical problems with the request. " 

75 "Responses with warnings should be treated as unstable. " 

76 "Warning descriptions must not be treated as machine readable " 

77 "and their schema can change at any time." 

78 ), 

79 "example": [ 

80 { 

81 "code": "partially invalid request parameter", 

82 "message": ( 

83 "Some of the request parameters were bad, " 

84 "but we were able to process the request. " 

85 "Here's some information that might help you " 

86 "fix the problem for future requests." 

87 ), 

88 } 

89 ], 

90 }, 

91 } 

92 

93 return { 

94 "type": "object", 

95 "properties": properties, 

96 "required": list(set(properties.keys()) - {"warnings"}), 

97 }