1- from rest_framework .response import Response
2- from rest_framework .pagination import PageNumberPagination
31from 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
418
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 } "
2122
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
2727
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+ ])
3040
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
3344
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