1
- from rest_framework .response import Response
2
- from rest_framework .pagination import PageNumberPagination
3
1
from collections import OrderedDict
2
+ from math import ceil
3
+ from django .core .paginator import Paginator
4
+ from rest_framework .response import Response
5
+ from urllib .parse import urlparse
6
+
7
+ def paginate (request , queryset , serializer_class , per_page = 10 , wrap = 'data' , additional_data = None ):
8
+ # Get per_page from query params if present, otherwise use default
9
+ per_page = int (request .query_params .get ('per_page' , per_page ))
10
+ page = int (request .query_params .get ('page' , 1 ))
11
+ total = queryset .count ()
12
+ last_page = ceil (total / per_page )
13
+ offset = (page - 1 ) * per_page
14
+
15
+ paginated_queryset = queryset [offset :offset + per_page ]
16
+ serializer = serializer_class (paginated_queryset , many = True )
17
+ data = serializer .data
4
18
5
- class LaravelStylePagination (PageNumberPagination ):
6
- page_size = 10
7
-
8
- def get_paginated_response (self , data , wrap ):
9
- data = (OrderedDict ([
10
- ('per_page' , self .page_size ),
11
- ('current_page' , self .page .number ),
12
- ('last_page' , self .page .paginator .num_pages ),
13
- ('next_page_url' , self .get_next_link () or None ),
14
- ('prev_page_url' , self .get_previous_link () or None ),
15
- ('total' , self .page .paginator .count ),
16
- ('from' , self .page .start_index ()),
17
- ('to' , self .page .end_index ()),
18
- (wrap , data ),
19
- ]))
20
- return data
19
+ full_path = str (request .build_absolute_uri ())
20
+ parsed_url = urlparse (full_path )
21
+ path_without_query = f"{ parsed_url .scheme } ://{ parsed_url .netloc } { parsed_url .path } "
21
22
22
-
23
- def paginate (request , queryset , serializer_class , per_page = 2 , wrap = 'data' ):
24
- # Create an instance of the custom pagination class
25
- paginator = LaravelStylePagination ()
26
- paginator .page_size = per_page
23
+ first_page_url = f"{ path_without_query } ?page=1&per_page={ per_page } "
24
+ last_page_url = f"{ path_without_query } ?page={ last_page } &per_page={ per_page } "
25
+ next_page_url = f"{ path_without_query } ?page={ page + 1 } &per_page={ per_page } " if page < last_page else None
26
+ prev_page_url = f"{ path_without_query } ?page={ page - 1 } &per_page={ per_page } " if page > 1 else None
27
27
28
- # Paginate the queryset
29
- page = paginator .paginate_queryset (queryset , request )
28
+ # Convert all URLs to strings explicitly
29
+ response_data = OrderedDict ([
30
+ (wrap , data ),
31
+ ('total' , total ),
32
+ ('per_page' , int (per_page )), # ensure integer
33
+ ('current_page' , int (page )), # ensure integer
34
+ ('last_page' , int (last_page )), # ensure integer
35
+ ('first_page_url' , str (first_page_url )),
36
+ ('last_page_url' , str (last_page_url )),
37
+ ('next_page_url' , str (next_page_url ) if next_page_url else None ),
38
+ ('prev_page_url' , str (prev_page_url ) if prev_page_url else None ),
39
+ ])
30
40
31
- # Serialize the paginated data using the provided serializer class
32
- serializer = serializer_class (page , many = True )
41
+ # Merge additional_data if provided
42
+ if additional_data :
43
+ response_data ['additional_data' ] = additional_data
33
44
34
- # Return the paginated data along with pagination metadata
35
- return paginator .get_paginated_response (serializer .data , wrap )
45
+ return response_data
0 commit comments