42

我在模板中使用 django 分页器。它工作正常,但当有大量页面时效果不佳。

视图.py:

def blog(request):
    blogs_list = Blog.objects.all()

    paginator = Paginator(blogs_list, 1)

    try:
        page = int(request.GET.get('page', '1'))
    except:
        page = 1

    try:
        blogs = paginator.page(page)
    except(EmptyPage, InvalidPage):
        blogs = paginator.page(page)
    return render(request, 'blogs.html', {
        'blogs':blogs
        })

模板片段:

  <div class="prev_next">

    {% if blogs.has_previous %}
      <a class="prev btn btn-info" href="?page={{blogs.previous_page_number}}">Prev</a>
    {% endif %}
    {% if blogs.has_next %}
      <a class="next btn btn-info" href="?page={{blogs.next_page_number}}">Next</a>
    {% endif %}
    <div class="pages">
      <ul>
      {% for pg in blogs.paginator.page_range %}
        {% if blogs.number == pg %}
          <li><a href="?page={{pg}}" class="btn btn-default">{{pg}}</a></li>
        {% else %}
          <li><a href="?page={{pg}}" class="btn">{{pg}}</a></li>
        {% endif %}
      {% endfor %}
      </ul>
    </div>
    <span class="clear_both"></span>

  </div> 

现在看起来像这样:

在此处输入图像描述

我该怎么做才能仅显示 7 个页码,而不是所有从当前页码开始的页码,如下所示:

Prev 1 (2) 3 4 5 Next

我希望我很清楚,如果没有,请询​​问。非常感谢您的帮助和指导。谢谢你。

4

9 回答 9

77

要把这个扔进去。我想出了它,因为它让你知道两边都有更多的页面。

<ul class="pagination">

{% if page_obj.has_previous %}
    <li><a href="?page={{ page_obj.previous_page_number }}"><i class="fa fa-chevron-left" aria-hidden="true"></i></a></li>
{% else %}
    <li class="disabled"><span><i class="fa fa-chevron-left" aria-hidden="true"></i></span></li>
{% endif %}

{% if page_obj.number|add:'-4' > 1 %}
    <li><a href="?page={{ page_obj.number|add:'-5' }}">&hellip;</a></li>
{% endif %}

{% for i in page_obj.paginator.page_range %}
    {% if page_obj.number == i %}
        <li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
    {% elif i > page_obj.number|add:'-5' and i < page_obj.number|add:'5' %}
        <li><a href="?page={{ i }}">{{ i }}</a></li>
    {% endif %}
{% endfor %}

{% if page_obj.paginator.num_pages > page_obj.number|add:'4' %}
    <li><a href="?page={{ page_obj.number|add:'5' }}">&hellip;</a></li>
{% endif %}

{% if page_obj.has_next %}
    <li><a href="?page={{ page_obj.next_page_number }}"><i class="fa fa-chevron-right" aria-hidden="true"></i></a></li>
{% else %}
    <li class="disabled"><span><i class="fa fa-chevron-right" aria-hidden="true"></i></span></li>
{% endif %}

</ul>

它看起来像这样:

用省略号分页

于 2017-09-20T18:43:02.133 回答
45

另一个使用模板的较短解决方案是将当前的 forloop.counter 与特定范围进行比较。

使用引导程序我使用这个模板

<nav aria-label="Page navigation">   <ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
  <a class="page-link" href="?page=1" aria-label="Previous">
    <span aria-hidden="true">&laquo;</span>
    <span class="sr-only">begin</span>
  </a>
</li>   {% endif %}

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

{% if page_obj.has_next %}
  <li class="page-item">
    <a class="page-link" href="?page={{ page_obj.paginator.num_pages }}" aria-label="Next">
      <span aria-hidden="true">&raquo;</span>
      <span class="sr-only">end</span>
    </a>
  </li>
  {% endif %}   </ul> </nav>

截屏

于 2017-08-16T15:26:16.087 回答
33

首先,我将更改以下内容:

try:
    blogs = paginator.page(page)
except(EmptyPage, InvalidPage):
    blogs = paginator.page(page)  # Raises the same error

但是你可以在你的上下文中传递一个范围。

index = paginator.page_range.index(blogs.number)
max_index = len(paginator.page_range)
start_index = index - 3 if index >= 3 else 0
end_index = index + 3 if index <= max_index - 3 else max_index
page_range = paginator.page_range[start_index:end_index]

现在您应该能够遍历范围以构建正确的链接?page=

=== 编辑 ===
所以你的视图会是这样的:

def blog(request):
    paginator = Paginator(Blog.objects.all(), 1)

    try:
        page = int(request.GET.get('page', '1'))
    except:
        page = 1

    try:
        blogs = paginator.page(page)
    except(EmptyPage, InvalidPage):
        blogs = paginator.page(1)

    # Get the index of the current page
    index = blogs.number - 1  # edited to something easier without index
    # This value is maximum index of your pages, so the last page - 1
    max_index = len(paginator.page_range)
    # You want a range of 7, so lets calculate where to slice the list
    start_index = index - 3 if index >= 3 else 0
    end_index = index + 3 if index <= max_index - 3 else max_index
    # Get our new page range. In the latest versions of Django page_range returns 
    # an iterator. Thus pass it to list, to make our slice possible again.
    page_range = list(paginator.page_range)[start_index:end_index]

    return render(request, 'blogs.html', {
        'blogs': blogs,
        'page_range': page_range,
    })

所以现在我们必须编辑您的模板以接受我们的新页码列表:

<div class="prev_next">
    {% if blogs.has_previous %}
        <a class="prev btn btn-info" href="?page={{blogs.previous_page_number}}">Prev</a>
    {% endif %}
    {% if blogs.has_next %}
        <a class="next btn btn-info" href="?page={{blogs.next_page_number}}">Next</a>
    {% endif %}
    <div class="pages">
        <ul>
        {% for pg in page_range %}
            {% if blogs.number == pg %}
                <li><a href="?page={{pg}}" class="btn btn-default">{{pg}}</a></li>
            {% else %}
                <li><a href="?page={{pg}}" class="btn">{{pg}}</a></li>
            {% endif %}
        {% endfor %}
        </ul>
    </div>
    <span class="clear_both"></span>
</div>
于 2015-06-16T10:14:36.987 回答
9

我发现最简单的做法是创建一个分页片段,它只显示您想要的页面。

就我而言,我不想要任何上一个或下一个链接。我只是想总是有一个指向第一页和最后一页的链接,然后有当前页面和当前页面两侧的两个页面。

我的模板片段(使用来自 django-tables2 的变量 - 如果您Paginator直接使用 Django,变量的名称会略有不同)

{% load django_tables2 %}
{% load humanize %}
{% load i18n %}

{% if table.page %}
  {% with table.page.paginator.count as total %}
    {% with table.page.number as page_num %}
      {% with table.page.paginator.num_pages as num_pages %}
        {% block pagination %}
          <div class="row">
            <div class="col-md-12">    
              {% if table.paginator.num_pages > 1 %}
                <ul class="pagination pull-right">
                  {% for n in table.page.paginator.page_range %}
                    {% if table.page.number|add:'-3' == n %}
                      {# First page #}
                      <li><a href="{% querystring table.prefixed_page_field=1 %}">1</a></li>
                      {% if n != 1 %}
                        <li class="disabled"><a>&#8943;</a></li>
                      {% endif %}
                    {% elif table.page.number == n %}
                      {# Current page #}
                      <li class="active"><a href="#">{{ n }}</a></li>
                    {% elif table.page.number|add:'-3' < n and n < table.page.number|add:'3' %}
                      {# Pages around current page #}
                      <li><a href="{% querystring table.prefixed_page_field=n %}">{{ n }}</a></li>
                    {% elif table.page.number|add:'3' == n %}
                      {# Last page #}
                      {% if n != num_pages %}
                        <li class="disabled"><a>&#8943;</a></li>
                      {% endif %}
                      <li><a href="{% querystring table.prefixed_page_field=num_pages %}">{{ num_pages }}</a></li>
                    {% endif %}
                  {% endfor %}
                </ul>
              {% endif %}
            </div>
          </div>
        {% endblock pagination %}
      {% endwith %}
    {% endwith %}
  {% endwith %}
{% endif %}

我的分页在不同页面上的示例

1

2

3

4

5

6

信用:这是受到@Pavel1114 的回答的启发。

于 2017-09-01T15:40:58.317 回答
4

Django 3.2在 Paginator 类中引入了一个新特性

Paginator.get_elided_page_range(number, *, on_each_side=3, on_ends=2)

和 的默认值on_each_sideon_ends如果当前页面为 10 并且有 50 页,则页面范围将为[1, 2, '…', 7, 8, 9, 10, 11, 12, 13, '…', 49, 50]

于 2021-03-23T23:42:30.840 回答
3

你也可以扩展Paginator类。

class BootstrapPaginator(Paginator):
    def __init__(self, *args, **kwargs):
        """        
        :param wing_pages: How many pages will be shown before and after current page.
        """
        self.wing_pages = kwargs.pop('wing_pages', 3)
        super(BootstrapPaginator, self).__init__(*args, **kwargs)

    def _get_page(self, *args, **kwargs):
        self.page = super(BootstrapPaginator, self)._get_page(*args, **kwargs)
        return self.page

    @property
    def page_range(self):
        return range(max(self.page.number - self.wing_pages, 1),
                     min(self.page.number + self.wing_pages + 1, self.num_pages + 1))

然后在模板中:

{% for num in action_list.paginator.page_range %}
    {% if action_list.number == num %}
         <li class="active"><a href="?page={{ num }}">{{ num }}</a></li>
    {% else %}
         <li><a href="?page={{ num }}">{{ num }}</a></li>
    {% endif %}
{% endfor %}

现在page_range将只包含 7 个项目。wing_pages+ 当前页面 +wing_pages用于引导的自定义 django 分页器

于 2017-06-07T13:46:37.813 回答
2

受到@Pavel1114@Inti的启发。删除了开头和结尾的箭头,因为它们不是那么有用。添加了第一页和最后一页以便更快地访问。

<ul>
  <li class="grp-results">
      <span>{{paginator.count}} total</span>
  </li>
  {% if data.number|add:'-4' > 1 %}
    <li><a href="?page=1">1</a></li>
    <li><a href="?page={{ data.number|add:'-5' }}">&hellip;</a></li>
  {% endif %}
  {% for i in data.paginator.page_range %}
    {% if data.number == i %}
        <li class="active"><span>{{ i }}</span></li>
    {% elif i > data.number|add:'-3' and i < data.number|add:'3' %}
        <li><a href="?page={{ i }}">{{ i }}</a></li>
      {% endif %}
  {% endfor %}
  {% if data.paginator.num_pages > data.number|add:'4' %}
    <li><a href="?page={{ data.number|add:'5' }}">&hellip;</a></li>
    <li><a href="?page={{ data.paginator.count }}">{{ data.paginator.count }}</a></li>
  {% endif %}
</ul>

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

于 2020-03-25T23:50:01.817 回答
2

您可以使用以下代码。

     <nav aria-label="Page navigation example">
        <ul class="pagination justify-content-center">

            <li class="page-item {% if not page_obj.has_previous %} disabled {% endif %}">
                <a class="page-link" href="?page=1" tabindex="-1">FIRST</a>
            </li>
            <li class="page-item {% if not page_obj.has_previous %} disabled {% endif %}">
                <a class="page-link" href="{% if page_obj.has_previous %}?page={{ page_obj.previous_page_number }}{% endif %} " tabindex="-1">Previous</a>
            </li>

            {% if page_obj.number|add:'-4' > 1 %}
                <li class="page-item disabled"><a class="page-link" href="?page={{ page_obj.number|add:'-5' }}">&hellip;</a></li>
            {% endif %}

            {% for i in page_obj.paginator.page_range %}
                {% if page_obj.number == i %}
                    <li class="active page-item disabled"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
                {% elif i > page_obj.number|add:'-5' and i < page_obj.number|add:'5' %}
                    <li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
                {% endif %}
            {% endfor %}

            {% if page_obj.paginator.num_pages > page_obj.number|add:'4' %}
                <li class="page-item disabled"><a class="page-link" href="?page={{ page_obj.number|add:'5' }}">&hellip;</a></li>
            {% endif %}

            <li class="page-item {% if not page_obj.has_next %} disabled {% endif %}">
                <a class="page-link" href="{% if page_obj.has_next %} ?page={{ page_obj.next_page_number }} {% endif %}">Next</a>
            </li>
            <li class="page-item {% if not page_obj.has_next %} disabled {% endif %}">
                <a class="page-link" href="{% if page_obj.has_next %} ?page={{ page_obj.paginator.num_pages }}  {% endif %}">LAST</a>
            </li>
        </ul>
    </nav>  

在此处输入图像描述

于 2020-05-24T00:35:23.613 回答
1

我只在带有表达式的模板上这样做:

{% if is_paginated %}
    <div class="text-center">
        <ul class="pagination pagination-sm">
            {% if page_obj.number >= 5 %}
            <li><a href="?page=1">1</a></li>
            <li><span>...</span></li>
            {% elif page_obj.number == 4 %}
            <li><a href="?page=1">1</a></li>
            {% endif %}
            {% if page_obj.number|add:"-2" >= 1  %}
            <li><a href="?page={{ page_obj.number|add:"-2" }}">{{ page_obj.number|add:"-2" }}</a></li>
            {% endif %}
            {% if page_obj.number|add:"-1" >= 1  %}
            <li><a href="?page={{ page_obj.number|add:"-1" }}">{{ page_obj.number|add:"-1" }}</a></li>
            {% endif %}
            <li class="active"><a href="?page={{ page_obj.number }}">{{ page_obj.number }}</a></li>
            {% if page_obj.number|add:"1" <= paginator.num_pages  %}
            <li><a href="?page={{ page_obj.number|add:"1" }}">{{ page_obj.number|add:"1" }}</a></li>
            {% endif %}
            {% if page_obj.number|add:"2" <= paginator.num_pages %}
            <li><a href="?page={{ page_obj.number|add:"2" }}">{{ page_obj.number|add:"2" }}</a></li>
            {% endif %}
            {% if page_obj.number|add:"2" <= paginator.num_pages|add:"-2" %}
            <li><span>...</span></li>
            <li><a href="?page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a></li>
            {% elif page_obj.number|add:"1" <= paginator.num_pages|add:"-2" %}
            <li><a href="?page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a></li>
            {% endif %}
        </ul>
    </div>
{% endif %}

我知道 django 就像“不要再写你的代码”,但我发现这对我来说更容易理解。希望我有所帮助。

于 2017-06-08T17:51:53.370 回答