Skip to content

Commit

Permalink
Merge pull request #21 from uktrade/feature/pagination
Browse files Browse the repository at this point in the history
chore:enhance pagination handling for search results
  • Loading branch information
hareshkainthdbt authored Oct 16, 2024
2 parents f88a6a6 + 95c7ce1 commit 9f8e7f0
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 32 deletions.
43 changes: 34 additions & 9 deletions orp/orp_search/public_gateway.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import logging

from typing import Tuple

import pandas as pd
import requests # type: ignore

from jinja2 import Template
from orp_search.config import SearchDocumentConfig
from orp_search.dummy_data import get_construction_data_as_dataframe

from django.core.paginator import InvalidPage, Paginator

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -35,20 +39,40 @@ def _build_like_conditions(self, field, terms):
"""
return " OR ".join([f"{field} LIKE '%{term}%'" for term in terms])

def paginate_results(self, config: SearchDocumentConfig, results):
def paginate_results(
self, config: SearchDocumentConfig, results, context
) -> Tuple[dict, Paginator]:
"""
Paginates the search results.
Paginates the given search results based on the provided configuration.
Args:
results (list): The search results to paginate.
Arguments:
config (SearchDocumentConfig): Configuration parameters for search,
including pagination limits.
results: A collection of search results to be paginated.
context: A dictionary containing context data which will be updated
with pagination details.
Returns:
list: The paginated search results.
count: Total number of pages from results
A tuple containing:
- Updated context dictionary with pagination information.
- Paginator instance used for paginating the results.
The context dictionary is updated with the following keys:
is_paginated: A boolean indicating if the results span multiple pages.
reports: The paginated results for the current page.
paginator: The Paginator instance.
page_obj: The current page of results.
"""
start = (config.offset - 1) * config.limit
end = start + config.limit
return results[start:end]
paginator = Paginator(results, config.limit)
try:
paginated_reports = paginator.page(config.offset)
except InvalidPage:
paginated_reports = paginator.page(1)
context["is_paginated"] = paginator.num_pages > 1
context["reports"] = paginated_reports
context["paginator"] = paginator
context["page_obj"] = paginated_reports
return context, paginator

def calculate_total_pages(self, config, results_count):
"""
Expand All @@ -61,6 +85,7 @@ def calculate_total_pages(self, config, results_count):
Returns:
int: The total number of pages.
"""

if config.limit <= 0:
raise ValueError("limit must be greater than 0")
return (results_count + config.limit - 1) // config.limit
Expand Down
54 changes: 31 additions & 23 deletions orp/orp_search/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,32 +174,40 @@ def search(request: HttpRequest) -> HttpResponse:
# on the landing page.

if search_results:
paginated_search_results = public_gateway.paginate_results(
config, search_results
)
logger.info(
"paginated search results after paginate: %s",
paginated_search_results,
context, paginator = public_gateway.paginate_results(
config, search_results, context
)

# Initialize a list to hold all results from all pages
paginated_search_results = []

# Iterate over each page
for page_num in paginator.page_range:
# Get the page
page = paginator.page(page_num)
# Add the objects of the current page to the aggregate list

for result in page.object_list:
paginated_search_results.append(
{
"id": result["id"],
"title": result["title"],
"publisher": result["publisher"],
"description": (
result["description"][:100] + "..."
if len(result["description"]) > 100
else result["description"]
),
"date_issued": result["date_issued"],
"date_modified": result["date_modified"],
"document_type": result["type"],
"regulatory_topics": result["regulatory_topics"].split(
"\n"
),
}
)

# We can use the following code to filter the search_results list:
paginated_search_results = [
{
"id": result["id"],
"title": result["title"],
"publisher": result["publisher"],
"description": (
result["description"][:100] + "..."
if len(result["description"]) > 100
else result["description"]
),
"date_issued": result["date_issued"],
"date_modified": result["date_modified"],
"document_type": result["type"],
"regulatory_topics": result["regulatory_topics"].split("\n"),
}
for result in paginated_search_results
]
context["results_count"] = len(paginated_search_results)
else:
paginated_search_results = []
Expand Down

0 comments on commit 9f8e7f0

Please sign in to comment.