summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2017-09-30 11:28:56 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2017-09-30 11:28:56 +0200
commitc073239b4ff54fdf9334e53137219c4da611118c (patch)
tree34e5cd326e2f5380ddd4ecfb10d712fde1cd28ef
parent4d7c7c9410d86160cfac73c0e1ace599b9e34a73 (diff)
downloadChimère-c073239b4ff54fdf9334e53137219c4da611118c.tar.bz2
Chimère-c073239b4ff54fdf9334e53137219c4da611118c.zip
Manage search pagination
-rw-r--r--chimere/models.py36
-rw-r--r--chimere/templates/search/search.html6
-rw-r--r--chimere/views.py40
-rw-r--r--settings.py2
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 %}
</ul>
</div>
-{% if page.has_previous or page.has_next %}
+{% if previous_page_number or next_page_number %}
<div id='search-nav'>
<nav>
<ul class="pager">
- {% if page.has_previous %}<li class="previous"><a href="#" onclick="haystack_search(this, {{ page.previous_page_number }});">&larr; {% trans "Previous" %}</a></li>{% endif %}
- {% if page.has_next %}<li class="next"><a href="#" onclick="haystack_search(this, {{ page.next_page_number }});">{% trans "More results..." %} &rarr;</a></li>{% endif %}
+ {% if previous_page_number %}<li class="previous"><a href="#" onclick="haystack_search(this, {{ previous_page_number }});"><i class="fa fa-arrow-circle-left" aria-hidden="true"></i> {% trans "Previous" %}</a></li>{% endif %}
+ {% if next_page_number %}<li class="next"><a href="#" onclick="haystack_search(this, {{ next_page_number }});">{% trans "More results..." %} <i class="fa fa-arrow-circle-right" aria-hidden="true"></i></a></li>{% endif %}
</ul>
</nav>
</div>
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