Im currently regrouping some data and then displaying that data in columns whilst also using pagination. However, due to the ordering of the origin data, there are instances where column 1 has 1 entry in but actually has 5 or 6 total entries, but they would be on different pages, is it possible to regroup the data so that the number of items per page is taken by the number of grouped items?
I thought about sorting the data before posting it to the page but then that will only show the one column of types per page (there could be 1 or n types/columns that id like to have on one page)
note: the sample data below is not actual data,
The below example hopefully will make things clearer
orgin data:
ID Type Item
----------------------------
9 Fruit Apple
15 Meat Beef
18 Fruit Lemon
99 Fruit Orange
9 Fruit Grape
77 Meat Chicken
Paginated and grouped data current output
Meat Fruit
------- -------
Beef Apple
Lemon
page 1 of 2 (3 items per page)
Meat Fruit
------- -------
Chicken Orange
Grape
page 2 of 2 (3 items per page)
Desired Output
Meat Fruit
------- -------
Beef Apple
Chicken Lemon
Orange
page 1 of 2 (3 items per group per page)
Meat Fruit
------- -------
Grape
page 2 of 2 (3 items per group per page)
This is my current template:
{% include 'search/page_nav.html' %}
{% with results.object_list as results_list %}
{% regroup results_list|dictsort:"model_name" by model_name as grouped_objects %}
{% for ct in grouped_objects %}
<div class="col-4">
<h3 class="text-capitalize">{{ ct.grouper }}'s</h3>
{% for result in ct.list %}
<div class="col-12 results">
<div class="pt-4 border-bottom">
<a class="page-url h4 text-primary" href="{{ result.object.get_absolute_url }}">{{ result.object.get_search_title }}</a>
<p class="page-description mt-1 text-muted"> {{ result.object.get_search_text|safe }}</p>
</div>
</div>
{% endfor %}
</div>
{% empty %}
<p class="lead">Although I am a guru, I am lacking sentience. One must ask a specific question to recieve a specific answer.</p>
{% endfor %}
{% endwith %}
{% include 'search/page_nav.html' %}
and the pagination template:
{% if results.has_previous or results.has_next %}
<nav class="col-12" aria-label="Page navigation">
<ul class="pagination mb-2">
<li class="page-item {% if not results.has_previous %} disabled {% endif %}"><a class="page-link" href="{% if results.has_previous %}?q={{ query }}&page={{ results.previous_page_number }}{% endif %}">Previous</a>
{% if results.number|add:'-5' > 1 %}
<li class="page-item active}"><a class="page-link" href="?q={{ query }}&page={{ results.number|add:'-5' }}">…</a></li>
{% endif %}
{% for i in results.paginator.page_range %}
{% if results.number == i %}
<li class="page-item active"><a class="page-link" href="?q={{ query }}&page={{ i }}">{{ i }}</a></li>
{% elif i > results.number|add:'-6' and i < results.number|add:'6' %}
<li class="page-item"><a class="page-link" href="?q={{ query }}&page={{ i }}">{{ i }}</a></li>
{% endif %}
{% endfor %}
{% if results.paginator.num_pages > results.number|add:'5' %}
<li class="page-item active}"><a class="page-link" href="?q={{ query }}&page={{ results.number|add:'5' }}">…</a></li>
{% endif %}
<li class="page-item {% if not results.has_next %} disabled {% endif %}"><a class="page-link" href="{% if results.has_next %}?q={{ query }}&page={{ results.next_page_number }}{% endif %}">Next</a>
<li class="page-item" style="padding: 0.3rem 0.75rem">(Page {{ results.number }} of {{ results.paginator.num_pages }})</li>
</ul>
</nav>
{% endif %}
Edit:
the view is a haystack query code below:
from haystack.query import SearchQuerySet
from haystack.inputs import AutoQuery, Exact, Clean
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
sqs = SearchQuerySet().filter(content=AutoQuery(query))
# create the pagination
paginator = Paginator(sqs, 10)
page = request.GET.get('page')
try:
results = paginator.page(page)
except PageNotAnInteger:
results = paginator.page(1)
except EmptyPage:
results = paginator.page(paginator.num_pages)
SQS object returned:
>>> sqs
<SearchQuerySet: query=<haystack.backends.elasticsearch5_backend.Elasticsearch5SearchQuery object at 0x7ff0e549f5f8>, using=None>
>>> vars(sqs[0])
{'app_label': 'config', 'model_name': 'devicecircuitsubnets', 'pk': '6788', 'score': 8.327476, '_object': None, '_model': None, '_verbose_name': None, '_additional_fields': ['id', 'text'], '_point_of_origin': None, '_distance': None, 'stored_fields': None, 'log': <haystack.utils.log.LoggingFacade object at 0x7ff0e525e7f0>, 'id': 'config.devicecircuitsubnets.6788', 'text': 'WAN-EDGE\nBarb\n\n\n\n\n102.155.156.2\nRouted Link\n\n'}
>>>
>>> sqs.count()
44
so the first regroup would be done with model_name and score, which should create x amount of model_groups with x amount of results in each of them, and these results should be paginated... hopefully this all makes sense?
EDIT:
here's the full output of a search and then the object list after pagination
>>> from haystack.query import SearchQuerySet
>>> from haystack.inputs import AutoQuery, Exact, Clean
>>> from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
>>> query ='edge'
>>> sqs = SearchQuerySet().filter(content=AutoQuery(query))
>>> paginator = Paginator(sqs, 10)
>>> page = 1
>>> results = paginator.page(page)
>>> results
<Page 1 of 5>
>>> var(results)
>>> vars(results)
{'object_list': [<SearchResult: config.devicecircuitsubnets (pk='6788')>, <SearchResult: config.devicecircuitsubnets (pk='6992')>, <SearchResult: config.devicecircuitsubnets (pk='7276')>, <SearchResult: config.device (pk='5')>, <SearchResult: config.devicecircuitsubnets (pk='694')>, <SearchResult: config.devicecircuitsubnets (pk='702')>, <SearchResult: config.devicecircuitsubnets (pk='7405')>, <SearchResult: config.devicecircuitsubnets (pk='695')>, <SearchResult: config.devicecircuitsubnets (pk='700')>, <SearchResult: config.devicecircuitsubnets (pk='1804')>], 'number': 1, 'paginator': <django.core.paginator.Paginator object at 0x7f30517037f0>}
>>> results.object_list
[<SearchResult: config.devicecircuitsubnets (pk='6788')>, <SearchResult: config.devicecircuitsubnets (pk='6992')>, <SearchResult: config.devicecircuitsubnets (pk='7276')>, <SearchResult: config.device (pk='5')>, <SearchResult: config.devicecircuitsubnets (pk='694')>, <SearchResult: config.devicecircuitsubnets (pk='702')>, <SearchResult: config.devicecircuitsubnets (pk='7405')>, <SearchResult: config.devicecircuitsubnets (pk='695')>, <SearchResult: config.devicecircuitsubnets (pk='700')>, <SearchResult: config.devicecircuitsubnets (pk='1804')>]
>>> vars(results.object_list[0])
{'app_label': 'config', 'model_name': 'devicecircuitsubnets', 'pk': '6788', 'score': 8.327476, '_object': None, '_model': None, '_verbose_name': None, '_additional_fields': ['id', 'text'], '_point_of_origin': None, '_distance': None, 'stored_fields': None, 'log': <haystack.utils.log.LoggingFacade object at 0x7f3050c83ba8>, 'id': 'config.devicecircuitsubnets.6788', 'text': 'WAN-EDGE\nBarb\n\n\n\n\n10.1.1.1\nRouted Link\n\n'}
>>>
Thanks
I ended up just posting the sqs query to the Django template sorted and then regrouping and using query to paginate each column.
sample below:
<div class="col-lg-12">
<div class="row">
{% if query %}
{% regroup results|dictsort:"model_name" by model_name as grouped_objects %}
{% for ct in grouped_objects %}
<div class="col-6 col-lg-3">
<h3 class="text-capitalize">{{ ct.grouper|friendly_search_name }}</h3>
<ul id="pager_{{ ct.grouper }}" class="pagination-sm mt-1"></ul>
<div id="pager_content_{{ ct.grouper }}">
{% for result in ct.list %}
<div class="col-12 results item">
<div class="pt-4 border-bottom">
<a class="page-url h4 text-primary" href="{{ result.object.get_absolute_url }}">{{ result.object.get_search_title }}</a>
<p class="page-description mt-1 text-muted"> {{ result.object.get_search_text|safe }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
{% empty %}
<p class="lead">Although I am a guru, I am lacking sentience. One must ask a specific question to recieve a specific answer.</p>
{% endfor %}
{% else %}
{# Show some example queries to run, maybe query syntax, something else? #}
{% endif %}
</div>
</div>
jquery:
{% block extrajs %}
<script src="{% static 'scripts/twbs-pagingation/jquery.twbsPagination.js' %}" type="text/javascript"></script>
<script type="text/javascript">
window.jQuery(function(){
var items_per_page = 4;
function hide_all(child) {
child.removeClass('active');
}
function show_page(child, num, items_per_page) {
hide_all(child);
child.slice((num-1)*items_per_page, num*items_per_page).addClass('active');
}
{% regroup results|dictsort:"model_name" by model_name as grouped_objects %}
{% for ct in grouped_objects %}
var $content_{{ ct.grouper }} = $('#pager_content_{{ ct.grouper }}');
var $child_{{ ct.grouper }} = $content_{{ ct.grouper }}.children();
$('#pager_{{ ct.grouper }}').twbsPagination({
totalPages: Math.ceil($child_{{ ct.grouper }}.length/items_per_page),
visiblePages: 5,
onPageClick: function (event, page) {
show_page($child_{{ ct.grouper }}, page, items_per_page);
}
});
{% endfor %}
});
</script>
{% endblock extrajs %}
{% block extrastyle %}
<style type="text/css">
.item {
display: none;
}
.item.active {
display: block;
}
</style>
{% endblock extrastyle %}