Home > Software design >  Django ListView filter and orderby with pagination
Django ListView filter and orderby with pagination

Time:08-28

I'm building a simple e-commerce website. I'm using ListView to represent home page of website that displays items. I want to be able to filter Items by their category and be able to order by some factor (for example price). By default it should show all items. And if there is another page of items of given kind it should keep filter. Question is how do I connect filter function with anchor tags in my home-page.html and make it work with multiple pages of filtered items?

My code.

views.py:

from django.views.generic import ListView,
from .models import ShopItem

class HomeView(ListView):
    model = ShopItem
    paginate_by = 2
    template_name = "home-page.html"

    def get_queryset(self):
        q = self.request.GET.get('filter', '')
        if not q:
            return self.model.objects.all()
        return self.model.objects.filter(category=q)

models.py:

from django.db import models

class ShopItem(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=100)
    description = models.TextField()
    category = models.CharField(max_length=15)
    price = models.FloatField()
    discount_price = models.FloatField(blank=True, null=True)
    slug = models.SlugField()

home-page.html:

<li >
  <a  href="/">All
    <span >(current)</span>
  </a>
</li>
<li >
  <a  href="#">Necklace</a>
</li>
<li >
  <a  href="#">Earrings</a>
</li>
<li >
  <a  href="#">Bracelets</a>
</li>

{% if is_paginated %}
<nav >
  <ul >

    {% if page_obj.has_previous %}
    <li >
      <a  href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
        <span >Previous</span>
      </a>
    </li>
    {% endif %}
    {% for page in page_obj.paginator.page_range %}
      {% if page_obj.number == page %}
        <li >
          <a  href="?page={{ page }}">{{ page }}
            <span >(current)</span>
          </a>
        </li>
        {% else %}
        <li >
          <a  href="?page={{ page }}">{{ page }}
            <span >{{ page }}</span>
          </a>
        </li>
        {% endif %}
    {% endfor %}

    {% if page_obj.has_next %}
    <li >
      <a  href="?page={{ page_obj.next_page_number }}" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
        <span >Next</span>
      </a>
    </li>
    {% endif %}
  </ul>
</nav>
{% endif %}

CodePudding user response:

of course it is not work. In your template you have hard-coded page links without filter.

    <li >
      <a  href="?page={{ page }}">
      <-- href should be something like "?page={{ page }}&filter={{filter}}" -->
      <-- or you can get filter from request "?page={{ page }}&filter={{request.GET.filter}}" -->
        {{ page }}
        <span >{{ page }}</span>
      </a>
    </li>

And, of course, don't forget to add 'filter' in context, if you use variable.

CodePudding user response:



      <!-- pagination from django-->
      {% if is_paginated %}
      <nav  aria-label="Page navigation">
        <ul >
          {% if page_obj.has_previous %}
          <li>
            <a href="?page={{ page_obj.previous_page_number }}" >&laquo; PREV 
            </a>
          </li>
          {% endif %}
          {% if page_obj.has_next %}
          <li>
            <a href="?page={{ page_obj.next_page_number }}" > NEXT &raquo;
            </a>
          </li>
          {% endif %}
        </ul>
      </nav>
      {% endif %}
  • Related