分页的实现

Posted paulwhw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分页的实现相关的知识,希望对你有一定的参考价值。

分页的实现

简述

对于“分页”,大家肯定再熟悉不过了,当一个网页的同类的内容在一页显示不全的时候,我们通常的解决方案都是在本页的同一区域做一个类似于“翻书”的功能,在‘第1页’显示前几条内容,‘第2页’显示另外的内容,以此类推,本文就为大家介绍在Django中如何实现分页功能

功能预览

本博客系统的分页功能预览如下:

技术分享图片

详细介绍

后台处理逻辑

首先,我们需要引入PaginatorEmptyPage类,后续的处理都需要依赖于这两个类。
接着,在index主页的视图函数中,我们不仅要获取本网站需要显示的所有文章的列表,还需要进行分页逻辑的处理。

分页逻辑的设计分为下面几步

一:首先,要确定每一页显示数据的个数,也就是说在获取所有文章的前提下利用Paginator类实例化出一个分页器对象来(我们这里限定每页显示三篇文章):
article_list = models.Article.objects.all()
paginator = Paginator(article_list,3)
注意,第一步实例化出的Paginator对象有三个参数需要大家记住,大家可以中途打印出来验证一下。
paginator.count         数据的总数
paginator.num_pages     总页数
paginator.page_range    页码的列表
二:接下来需要将当前页面对象current_page取出来
# 当前页,默认是第一页
current_page_c = int(request.GET.get(‘page‘, 1))
current_page = paginator.page(current_page_c)
三:其实在数据量小的情况下做完前两部就OK了。但是大家考虑下,如果我们的数据量特别大,大到需要分100多页甚至更多时才能显示完所有的数据,这样在网页中将会有100甚至更多的分页器数据。这样显然是不合理的。为了解决这个问题,我们还需要往模板中返回range对象,用来限制网站中分页器的页码显示:
# 最多显示11个格子
# 注意下面的判断——保证最多显示11个格子且“左5右5”,如果有越限的进行限制
# page_range_whw存的是range对象
if paginator.num_pages > 11:
    # “左5”越限
    if current_page_c - 5 < 1:
        page_range_whw = range(1, 11)
    # “右5”越限
    elif current_page_c + 5 > paginator.num_pages:
        page_range_whw = range(paginator.num_pages - 10, paginator.num_pages + 1)
    else:
        page_range_whw = range(current_page_c - 5, current_page_c + 6)
else:
    page_range_whw = paginator.page_range

后台完整代码

注意,对于分页器,往后台传了两个对象,一个是当前页对象current_page,另外一个是range对象page_range_whw
article_list = models.Article.objects.all()
paginator = Paginator(article_list, 3)
# print("count:", paginator.count)  # 数据总数
# print("num_pages", paginator.num_pages)  # 总页数
# print("page_range", paginator.page_range)  # 页码的列表
try:
    # 当前页,默认是第一页
    current_page_c = int(request.GET.get(‘page‘, 1))
    current_page = paginator.page(current_page_c)
    # 最多显示11个格子
    # 注意下面的判断——保证最多显示11个格子且“左5右5”,如果有越限的进行限制
    # page_range_whw存的是range对象
    if paginator.num_pages > 11:
        # “左5”越限
        if current_page_c - 5 < 1:
            page_range_whw = range(1, 11)
        # “右5”越限
        elif current_page_c + 5 > paginator.num_pages:
            page_range_whw = range(paginator.num_pages - 10, paginator.num_pages + 1)
        else:
            page_range_whw = range(current_page_c - 5, current_page_c + 6)
    else:
        page_range_whw = paginator.page_range
except EmptyPage as e:
    current_page = paginator.page(1)
return render(request,‘index.html‘,locals())

前端模板的渲染

对于前端模板的渲染比较简单,这里就不做详细的介绍了,但是,需要注意的一点是,由于我们做了分页器,那么在‘遍历‘文章列表的时候,我们遍历的对象不再是‘article_list’了,而是当前页对象‘current_page‘,这一点要特别注意!

文章列表渲染与分页器前端实现的代码

{# 文章列表部分 #}
<div class="col-md-6">
    <div class="article-list" style="position: fixed;width: 46%;">
        {# 注意,做分页的时候,循环“当前页”而不是所有的article_list #}
        {% for article in current_page %}
            <div class="article-item">
                <h5><a href="/{{ article.user }}/articles/{{ article.pk }}/">{{ article.title }}</a></h5>
                <div class="article-desc">
                    <span class="media-left">
                                                                                  {# 正向查询按字段 #}
                        <a href=""><img width="55px" height="55px" src="media/{{ article.user.avatar }}" ></a>
                    </span>
                    <span class="media-right">
                        {{ article.desc }}
                    </span>
                </div>
                <div class="small pub_info">
                                        {# 正向查询按字段 #}
                    <span><a href="">{{ article.user.username }}</a></span>&nbsp;&nbsp;
                    <span><a href="">发布于 {{ article.create_date|date:‘Y-m-d H:i‘ }}</a></span>&nbsp;&nbsp;
                    <span class="glyphicon glyphicon-comment"></span>评论({{ article.content_count }})&nbsp;&nbsp;
                    <span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article.up_count }})
                    <hr>
                </div>
            </div>
        {% endfor %}
    </div>
    {# 分页器 #}
    <div style="position: fixed;margin-top: 38%">
        <nav aria-label="Page navigation">
            <ul class="pagination">
                {% if current_page.has_previous %}
                    <li><a href="?page={{ current_page.previous_page_number }}" aria-label="Previous">
                            <span aria-hidden="true">上一页</span></a></li>
                {% else %}
                    <li class="disabled"><a href="" aria-label="Previous">
                            <span aria-hidden="true">上一页</span></a></li>
                {% endif %}

                {% for item in page_range_whw %}
                    {% if current_page_c == item %}
                        <li class="active"><a href="?page={{ item }}">{{ item }}</a></li>
                    {% else %}
                        <li><a href="?page={{ item }}">{{ item }}</a></li>
                    {% endif %}
                {% endfor %}

                {% if current_page.has_next %}
                    <li><a href="?page={{ current_page.next_page_number }}" aria-label="Next">
                            <span aria-hidden="true">下一页</span></a></li>
                {% else %}
                    <li class="disabled"><a href="" aria-label="Next"><span aria-hidden="true">下一页</span></a>
                    </li>
                {% endif %}
            </ul>
        </nav>
    </div>
</div>

以上是关于分页的实现的主要内容,如果未能解决你的问题,请参考以下文章

用datalist如何实现分页的代码(C#)

HTML中有没有让打印时强制分页的代码?

请高人讲解java ajax实现分页的思路

分页的简单实现

基于mybatis ajax 分页的实现

MyBatis:分页的实现