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

Time:01-02

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    >

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

    <li  >
      <a  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  aria-current="page">
      <a  href="/?page={{i}}" span >{{i}}</span></a>
    </li>
    {% else %}
    <li  id="{{i}}" value="{{i}}"><a  href="/?page={{i}}">{{i}}</a></li>
    {% endif %}
    {% endfor %}
    {% if page_obj.has_next %}
    <li >
      <a  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="/" >
  <input  name="search" id="search" type="search" placeholder="Search" aria-label="Search">
  <button  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>

CodePudding user response:

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 }}"  tabindex="-1" aria-disabled="true">Previous</a>

and this for all URL links.

  • Related