diff --git a/core/api/user/views.py b/core/api/user/views.py index 799822f..d02da1f 100644 --- a/core/api/user/views.py +++ b/core/api/user/views.py @@ -16,7 +16,8 @@ from utils import ( gen_response, error_response, - setLogger + setLogger, + paginate ) from schemas.user_schemas import ( AddNewUserSchema, @@ -183,9 +184,15 @@ def fetch_user(current_user): @permission_required(Permission.service_request) def fetch_bookings_for_user(current_user): """ fetch all bookings made by a user """ - bookings = current_user.bookings.order_by( + query = current_user.bookings.order_by( desc(Booking.created_at) - ).all() + ) + + pagination = paginate( + query=query, + page=request.args.get("page", 1, type=int), + per_page=request.args.get("per_page", 10, type=int), + ) msg = 'fetched top recent bookings successfully' schema = BookingSchema( @@ -205,8 +212,15 @@ def fetch_bookings_for_user(current_user): return gen_response( 200, - data=schema.dump(bookings), - message=msg + data={ + "bookings": schema.dump(pagination.items), + "page": pagination.page, + "per_page": pagination.per_page, + "total": pagination.total, + "pages": pagination.pages + }, + message=msg, + ) diff --git a/utils.py b/utils.py index 8581b9e..3185af8 100644 --- a/utils.py +++ b/utils.py @@ -8,6 +8,9 @@ import mimetypes import subprocess +from math import ceil +from flask import request +from sqlalchemy import select, func from loguru import logger from flask import jsonify from google.cloud import storage @@ -386,3 +389,54 @@ def decode_id(val): # response = requests.post(url, data=payload, headers=headers) # print(response.text) + + +def paginate(query, page=1, per_page=10, sort_key=None, session=None): + """ + Paginate a SQLAlchemy query. + + :param query: The query to paginate. + :param page: The page number to retrieve. + :param per_page: The number of items per page. + :return: A paginated query object. + """ + if session: + total = session.scalar(select(func.count()).select_from(query.subquery())) + else: + total = query.count() + + page = max(1, request.args.get("page", page, type=int)) + per_page = max(1, request.args.get("per_page", per_page, type=int)) + + pages = ceil(total / per_page) if total else 1 + + if sort_key: + paginated_query = query.order_by( + sort_key + ).limit(per_page).offset((page - 1) * per_page) + else: + paginated_query = query.limit(per_page).offset((page - 1) * per_page) + return PaginatedQuery(paginated_query, page, per_page, total, pages) + + +class PaginatedQuery: + """ + A paginated SQLAlchemy query object. + """ + + def __init__(self, query, page, per_page, total, pages): + self.query = query + self.page = page + self.per_page = per_page + self.total = total + self.pages = pages + + @property + def items(self): + """ + Get the data for the current page. + """ + return self.query.all() + + def scalars(self, session): + return session.scalars(self.query) \ No newline at end of file