Pagination of search results only in Django not working

Viewed 581

I have implemented a search bar and function into a django web app in the following view:

def search_products(request):
    search_query = request.GET.get('search', '')
    products = Product.objects.filter(Q(name__icontains=search_query) | Q(brand__icontains=search_query))
    paginator = Paginator(products, 40)
    page_number = request.GET.get('page', 1)
    page = paginator.get_page(page_number)
    if page.has_next():
        next_url = f'?page={page.next_page_number()}'
    else:
        next_url = ''

 

    if page.has_previous():
        prev_url = f'?page={page.previous_page_number()}'
    else:
        prev_url = ''

 

    return render(request, 'store/search_products.html',
                  context={'products': page.object_list, 'page': page, 'next_page_url': next_url,
                           'prev_page_url': prev_url})

The URLs are setup as follows:

urlpatterns = [
    path('', views.store_view, name='store'),
    path('wishlist/', views.wishlist_view, name='wishlist'),
    path('update_item/', views.updateItem, name='update_item'),
    path('search_products/', views.search_products, name='search_products'),
]

And the HTML for the search results is as follows:

<nav aria-label="Page navigation example">
          <ul class="pagination">
            <li class="page-item {% if not prev_page_url %} disabled {% endif %}">
              <a class="page-link" href="{{  prev_page_url }}" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
              </a>
            </li>

 

            {% for n in page.paginator.page_range %}
              {% if page.number == n %}
                <li class="page-item active" aria-current="page">
                    <a class="page-link" href="?page={{ n }}">{{ n }}
                    <span class="sr-only"></span>
                    </a></li>
              {% elif n > page.number|add:-4 and n < page.number|add:4 %}
                <li class="page-item">
                    <a class="page-link" href="?page={{ n }}">{{ n }}</a>
                </li>
                {% endif %}
            {% endfor %}

 


            <li class="page-item {% if not next_page_url %} disabled {% endif %}">
              <a class="page-link" href="{{ next_page_url  }}" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
              </a>
            </li>
          </ul>
        </nav>

I think the issue may be due to the fact that the search query enters the URL before the page number (?page={{ n }}), this may be wrong however. I am not sure how to fix this or implement this change. Any help would be appreciated.

1 Answers

The reason that your pagination is not working is that when u click on another page link the page query parameter replace the search query parameter and your search results will be gone.
The solution is to to append page query parameter to search query parameter it will be some thing like this for example url/?search=example&page=2
now I'm gonna tell you how to do that:

  1. Inside your app directory create a folder called templatetags

  2. Inside the templatetags folder create a file called pagination_tags.py(name is up to you)

    # Your template tag in app_name/templatetags/pagination_tags.py
    
    from django import template
    from urllib.parse import urlencode
    
    
    register = template.Library()
    
    @register.simple_tag
    def url_replace (request, field, value):
        dict_ = request.GET.copy()
        dict_[field] = value
    
        return dict_.urlencode()
    
  3. After creating your template tag load it in your html page and use it

    <!-- load your templatetag in your html file -->
    <!-- you should load your .py file -->
    {% load pagination_tags %}
    <!-- now you can use it -->
    
    <!-- Here is an Example to know how to use it -->
    <a class="page-link text-dark" href="?{% url_replace request 'page' 1 %}">1</a>
    <!-- first param is request , second param is is your lookup field and third param is your page number -->
    
Related