From c073239b4ff54fdf9334e53137219c4da611118c Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Sat, 30 Sep 2017 11:28:56 +0200 Subject: Manage search pagination --- chimere/models.py | 36 +++++++++++++++++++++++--------- chimere/templates/search/search.html | 6 +++--- chimere/views.py | 40 ++++++++++++++++++++++++++++++------ settings.py | 2 +- 4 files changed, 64 insertions(+), 20 deletions(-) diff --git a/chimere/models.py b/chimere/models.py index 46a778c..451596b 100644 --- a/chimere/models.py +++ b/chimere/models.py @@ -609,6 +609,7 @@ class GeographicItem(models.Model): search_vector = SearchVectorField(_("Search vector"), blank=True, null=True, help_text=_("Auto filled at save")) + geom_attr = '' default_values = {} json_color_keys = [] @@ -861,7 +862,8 @@ class GeographicItem(models.Model): raise NotImplementedError() @classmethod - def getGeoJSONs(cls, queryset, limit_to_categories=None, slice=None): + def getGeoJSONs(cls, queryset, limit_to_categories=None, slice=None, + check_next=False): default_values = copy.copy(cls.default_values) q_values = ['json', 'name', 'pk', 'categories__pk'] + \ cls.json_color_keys @@ -873,9 +875,8 @@ class GeographicItem(models.Model): start, end = 0, None if slice: start, end = slice + has_next = False for item in q.all(): - if end and len(vals) > end: - break if item['pk'] in added: continue if limit_to_categories and \ @@ -884,7 +885,11 @@ class GeographicItem(models.Model): added.append(item['pk']) if start: start -= 1 + end -= 1 continue + if end and len(vals) > end: + has_next = True + break properties = {"pk": item['pk'], "name": item['name'], 'key': "{}-{}".format(cls.geom_attr, item['pk'])} icon_and_colors, current_categories = \ @@ -905,18 +910,24 @@ class GeographicItem(models.Model): "geometry": geom, "properties": properties }) - return vals + if not check_next: + return vals + return vals, has_next @classmethod - def search(cls, query, area=None, get_json=False, slice=None): + def search(cls, query, area=None, get_json=False, slice=None, + check_next=False): """ Search items using search_vector :param query: terms to search :param area: area limitation (default None) :param get_json: output as json if True else return a queryset - :param slice: startting and ending bounds - :return: items matching the search query and the area + :param slice: starting and ending bounds + :param check_next: check if next items are available (only relevant + if a slice is provided) + :return: items matching the search query - if check next to true + also return if next items are available """ subcats = SubCategory.getAvailable(instance=True, area=area) q = cls.objects.filter(categories__in=subcats, @@ -924,11 +935,16 @@ class GeographicItem(models.Model): query, config=settings.CHIMERE_SEARCH_LANGUAGE)) if get_json: - return cls.getGeoJSONs(q, slice=slice) + return cls.getGeoJSONs(q, slice=slice, check_next=check_next) if slice: - return q.all()[slice[0]:slice[1]] + if not check_next: + return q.all()[slice[0]:slice[1]] + has_next = q.count() > slice[1] + return q.all()[slice[0]:slice[1]], has_next else: - return q.all() + if not check_next: + return q.all() + return q.all(), False def update_search_vector(self, save=True): """ diff --git a/chimere/templates/search/search.html b/chimere/templates/search/search.html index d01c16e..67e08d9 100644 --- a/chimere/templates/search/search.html +++ b/chimere/templates/search/search.html @@ -18,12 +18,12 @@ var end_do_you_mean = "{% trans '?' %}"; {% endfor %} -{% if page.has_previous or page.has_next %} +{% if previous_page_number or next_page_number %}
diff --git a/chimere/views.py b/chimere/views.py index ee27d26..d486506 100644 --- a/chimere/views.py +++ b/chimere/views.py @@ -1278,23 +1278,51 @@ class SearchView(FormView): form_class = forms.SearchForm results_per_page = settings.SEARCH_RESULTS_PER_PAGE - def get_results(self, query, area=None): - results = [] + def get_results(self, query, area=None, page=1): + results, has_next = [], False + start = (page - 1) * self.results_per_page + end = page * self.results_per_page - 1 for model in [models.Marker, models.Route, models.Polygon]: - results += model.search(query, area=area, get_json=True) - return results + if len(results) > end - len(results): + continue + res, _has_next = model.search( + query, area=area, get_json=True, + slice=[start, end], + check_next=True) + if _has_next: + has_next = True + if res: + if start: + end = end - start + start = 0 + end -= len(res) + results += res + return results, has_next def get_context_data(self, **kwargs): context = super(SearchView, self).get_context_data(**kwargs) area, area_name = get_area(self.kwargs.get('area_name', None)) query, results = None, [] + previous_page_number, next_page_number = None, None if "q" in self.request.GET: query = self.request.GET['q'] - results = self.get_results(query, area) + try: + page = int(self.request.GET.get('page', 1)) + assert page >= 1 + except (ValueError, AssertionError): + page = 1 + if page > 1: + previous_page_number = page - 1 + results, has_next = self.get_results(query, area, page=page) + if has_next: + next_page_number = page + 1 + context.update({ 'query': query, 'results': results, - 'area_name': area_name + 'area_name': area_name, + 'previous_page_number': previous_page_number, + 'next_page_number': next_page_number }) # (paginator, page) = self.build_page() diff --git a/settings.py b/settings.py index eadf6e4..41d6999 100644 --- a/settings.py +++ b/settings.py @@ -151,7 +151,7 @@ HAYSTACK_CONNECTIONS = { 'INCLUDE_SPELLING': True, }, } -SEARCH_RESULTS_PER_PAGE = HAYSTACK_SEARCH_RESULTS_PER_PAGE = 12 +SEARCH_RESULTS_PER_PAGE = HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10 HAYSTACK_AUTOCOMPLETE = False # length of short description -- cgit v1.2.3