Anthony Lee
Anthony Lee

Reputation: 243

Django pagination - How to limit the pages?

I'm using this code to display the pagination on my page

            <ul class="pagination pagination-sm">
                {% if restaurants.has_previous %}
                    <li><a href="?page={{ restaurants.previous_page_number }}">Prev</a></li>
                {% endif %}
                {% for page in restaurants.paginator.page_range %}
                    <li class="{% if restaurants.number == page %}active{% endif %}"><a
                            href="?page={{ page }}">{{ page }}</a></li>
                {% endfor %}

                {% if restaurants.has_next %}
                    <li><a href="?page={{ restaurants.next_page_number }}">Next</a></li>
                {% endif %}
            </ul>

The issue is that the code above shows all page like this:

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | and so on..

Instead I would like to show something like this:

1 | 2 | 3 | 4 | 5

How can I do that?

This is my view:

def listing(request):
    list_restaurants = ShopAccount.objects.filter(is_active=1)
    # only active products
    paginator = Paginator(list_restaurants, 20)  # Show 20 products per page

    page = request.GET.get('page')
    try:
        restaurants = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        restaurants = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        restaurants = paginator.page(paginator.num_pages)

    return render_to_response('restaurants/list.html', {'restaurants': restaurants}, context_instance=RequestContext(request))

Upvotes: 3

Views: 2494

Answers (3)

Tiago Iesbick
Tiago Iesbick

Reputation: 164

I solved this issue with JS.

Here the views:

class AllOrders(LoginRequiredMixin, ListView):
    model = Order
    template_name = 'all_orders.html'
    paginate_by = 20

    def get_queryset(self):
        filter_val = self.request.GET.get("filter", "")
        order_by = self.request.GET.get("orderby", "id")
        if filter_val != "":
            orders = Order.objects.filter(Q(transaction_id__contains=filter_val) |                                     Q(customer_id__auth_user_id__first_name__contains=filter_val) |
                                      Q(customer_id__auth_user_id__last_name__contains=filter_val)).order_by(order_by)
        else:
            orders = Order.objects.all().order_by(order_by)

        return orders

    def get_context_data(self, **kwargs):
        context = super(AllOrders, self).get_context_data(**kwargs)
        context["filter"] = self.request.GET.get("filter", "")
        context["orderby"] = self.request.GET.get("orderby", "id")
        context["all_table_fields"] = Order._meta.get_fields()
        return context

Here the template:

<nav class="d-inline-block">
  <ul class="pagination mb-0">
    {% if page_obj.has_previous %}
    <li class="page-item">
      <a class="page-link" href="{% url 'custom_user:all_orders' %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.previous_page_number }}" tabindex="-1"><i class="fas fa-chevron-left"></i></a>
    </li>
    {% else %}
    <li class="page-item disabled">
      <a class="page-link" href="#" tabindex="-1"><i class="fas fa-chevron-left"></i></a>
    </li>
    {% endif %}
    {% for i in paginator.page_range %}
      <li class="page-item {% if i == page_obj.number %}active{% endif %}"><a class="page-link" href="{% url 'custom_user:all_orders' %}?filter={{ filter }}&orderby={{ orderby }}&page={{ i }}">{{ i }} <span class="sr-only">(current)</span></a></li>
    {% endfor %}
    {% if page_obj.has_next %}
    <li class="page-item">
      <a class="page-link" href="{% url 'custom_user:all_orders' %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.next_page_number }}"><i class="fas fa-chevron-right"></i></a>
    </li>
    {% else %}
    <li class="page-item disabled">
      <a class="page-link" href="#"><i class="fas fa-chevron-right"></i></a>
    </li>
    {% endif %}
  </ul>
</nav>

Here the JS:

<script>
  let pages = document.getElementsByClassName('page-item');

  let pageActive;

  if (pages.length > 5) {
    for (let i = 0; i < pages.length; i++) {
      if (pages[i].classList.contains('active')){
        pageActive = i;
        break;
      }
    }
  for (let j = 0; j < pages.length; j++) {
    if ( j != 0 && j != 1 && j < (pageActive - 1)) {
      pages[j].setAttribute('hidden', true);
    } else if (j != (pages.length - 1) && j != (pages.length - 2) && j > (pageActive + 1)) {
      pages[j].setAttribute('hidden', true);
    }
  };
  };
</script>

This is the result: paginator

Upvotes: 0

vmonteco
vmonteco

Reputation: 15443

I use something like this :

<li {% ifequal page current %}class="active"{% endifequal %}>
  <a href={% ifequal page -4 %}
     "/blog/1/">&lt;&lt;
    {% else %}{% ifequal page -3 %}
     "/blog/{{ current | add:"-1" }}/">&lt;
    {% else %}{% ifequal page -2 %}
    "/blog/{{ current | add:"1" }}/">&gt;
    {% else %}{% ifequal page -1 %}
    "/blog/{{ maximum }}/">&gt;&gt;
    {% else %}{% ifequal page 0 %}
    "#">...
    {% else %}{% ifequal page current %}
    "#" class="page_link">{{ page }}
    {% else %}
     "/blog/{{ page }}/">{{ page }}
    {% endifequal %}
    {% endifequal %}
    {% endifequal %}
    {% endifequal %}
    {% endifequal %}
    {% endifequal %}
  </a>
</li>

and these views :

def makepaginator(current, maximum):
    """makepaginator() returns a set of number which reprensents buttons.                                                                                                                                                                    
    -4 means first page.                                                                                                                                                                                                                     
    -3 means previous page.                                                                                                                                                                                                                  
    -2 means next page.                                                                                                                                                                                                                      
    -1 means last page.                                                                                                                                                                                                                      
    0 means a dot.                                                                                                                                                                                                                           
    others means the number of the target page."""

    NB_PAGES_LEFT_LEFT = 3
    NB_PAGES_RIGHT_RIGHT = NB_PAGES_LEFT_LEFT
    NB_PAGES_CENTER_RIGHT = 3
    NB_PAGES_CENTER_LEFT = NB_PAGES_CENTER_RIGHT
    i = 2
    current = int(current)
    if current > 1:
    p = [-4, -3]
    else:
        p = []
    p.append(1)
    while i <= maximum:
        if (i > NB_PAGES_LEFT_LEFT and i < maximum - NB_PAGES_RIGHT_RIGHT
            and (i - current > NB_PAGES_CENTER_RIGHT
                 or current -  i > NB_PAGES_CENTER_RIGHT + 1)):
            p.append(0)
            while (i > NB_PAGES_LEFT_LEFT
                   and i < maximum - NB_PAGES_RIGHT_RIGHT
                   and (i - current > NB_PAGES_CENTER_RIGHT
                        or current - i > NB_PAGES_CENTER_LEFT + 1)):
                i += 1
        else:
            p.append(i)
        i += 1
    if current < maximum:
        p.append(-2)
        p.append(-1)
    return (p)

def news(request, page_num=1):
    paginator = Paginator(Article.objects.all().order_by('-date'), settings.ARTICLES_PER_PAGE)
    try :
        page = paginator.page(page_num)
    print(type(page_num))
        return (render(request, "main/blog.html",
                       {"paginator" : paginator, "page_num" : int(page_num),
                        "page" : page,
                        "buttons" : makepaginator(page_num,
                                                  paginator.num_pages)}))
    except (PageNotAnInteger, EmptyPage) as e:
        return (notfound(request))

With bootstrap I get this : pagination

It may look dirty but it works with my website. You can try it. If you have some improvements to suggests, I would be glad though. :)

Upvotes: 1

Jo&#227;o Vila&#231;a
Jo&#227;o Vila&#231;a

Reputation: 621

ShopAccount.objects.filter(is_active=1)[:5]

Try this code above, or use the [:5] on the paginator.

Upvotes: 0

Related Questions