Skip to content
Advertisement

Sorting and paginating object at the same time in django; after paginating the sort gets reset

If I have applied the sorting to my wallpapers and after that if I try to paginate the sorting gets reset. like if I have sorted wallpapers according to pub date in ascending order and after pagination, it gets back to normal.

view

def home(request):
WAllPAPER_PER_PAGE = 4
WALL = Wallpaper.objects.all()

from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
import json
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Q

ordering =request.GET.get('ordering', "")
search = request.GET.get('search', "")

if search:
    wallpapers = Wallpaper.objects.filter(Q(name__icontains=search) | 
    Q(category__category_name__icontains=search) | Q(tags__tag__icontains=search))

else:
    wallpapers = Wallpaper.objects.all()

if ordering:
    wallpapers = wallpapers.order_by(ordering)
page = request.GET.get('page', 1)
wallpaper_paginator = Paginator(wallpapers, WAllPAPER_PER_PAGE)
try:
    wallpapers = wallpaper_paginator.page(page)
except EmptyPage:
    wallpapers = wallpaper_paginator.page(wallpaper_paginator.num_pages)
except:
    wallpapers = wallpaper_paginator.page(WAllPAPER_PER_PAGE)
context = {"wallpapers": wallpapers, 'page_obj': wallpapers, 'is_paginated': True, 'paginator': wallpaper_paginator, 'WALL': WALL}
return render(request, "Wallpaper/Home.html", context)

Pagination code

{% if is_paginated %}
<nav class="pagination"   >

  <ul class="pagination" id="Pagination-list" >
    {% if page_obj.has_previous %}

    <li class="page-item" >
      <a class="page-link" tabindex="-1" aria-disabled="true"
        href="/?page={{ page_obj.previous_page_number }}">Previous</a>
    </li>
    {% endif %}
    {% for i in paginator.page_range %}
    {% if i == page_obj.number%}
    <li class="page-item active" aria-current="page">
      <a class="page-link" href="/?page={{i}}" span class="visually-hidden">{{i}}</span></a>
    </li>
    {% else %}
    <li class="page-item" id="{{i}}" value="{{i}}"><a class="page-link" href="/?page={{i}}">{{i}}</a></li>
    {% endif %}
    {% endfor %}
    {% if page_obj.has_next %}
    <li class="page-item">
      <a class="page-link" tabindex="-1" href="/?page={{ page_obj.next_page_number }}">Next</a>
    </li>
    {% endif %}
  </ul>

</nav>
{% endif %}

//Java script for searching and sorting sync


function get(name) {
  if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search)) //location.search give query sling part
    return decodeURIComponent(name[1]);
}

if (get('ordering'))
  document.getElementById('placeholder').innerHTML = "Sort: " + document.getElementById(get('ordering')).innerHTML;

if (get('page'))
  document.getElementById('Pagination-placeholder').innerHTML = "Pagination: " + document.getElementById(get('page')).innerHTML;



function finalurl() {
  var url = new URL(window.location.href);
  console.log(url)
  var search_params = url.searchParams;
  console.log(search_params)
  search_params.set('ordering', document.getElementById("sort-list").value);
  url.search = search_params.toString();
  var new_url = url.toString();
  console.log(new_url)
  return new_url
}
<!-- searching code -->

<form method="GET" action="/" class="d-flex">
  <input class="form-control me-2" name="search" id="search" type="search" placeholder="Search" aria-label="Search">
  <button class="btn btn-outline-success" type="submit">Search</button>
</form>

<!-- sorting HTML code -->

<select name="sort" id="sort-list" onchange="location = finalurl();" style="margin-left: auto;">
  <option value="" id="placeholder" disabled selected hidden>sort</option>
  <option id="pub_date" value="pub_date">Recently added</option>
  <option id="-pub_date" value="-pub_date">old post</option>
</select>

Advertisement

Answer

The reason this happens is because you “drop” the URL parameters regarding sorting and searching. You should each time add these to the pagination URLs.

In the view you can make a querystring for all the parameters except page with:

def home(request):
    qd = request.GET.copy()
    qd.pop('page', None)
    querystring = qd.urlencode()
    # …
    context = {'querystring': querystring, 'wallpapers': wallpapers, 'page_obj': wallpapers, 'is_paginated': True, 'paginator': wallpaper_paginator, 'WALL': WALL}
    return render(request, "Wallpaper/Home.html", context)

then in the template, you render the links to the other pages with:

<a href="/?page={{ page_obj.previous_page_number }}&amp;{{ querystring }}" class="page-link" tabindex="-1" aria-disabled="true">Previous</a>

and this for all URL links.

Advertisement