我的网站搭建(第3天) Django分页器

  • 发布时间:2015年12月5日 00:34
  • 作者:杨仕航

2016年7月5号修改:之前这篇文章写得一塌糊涂,现重新再写一次

我们的文章或者评论什么之类多了之后,如果用一个页面显示就会很长,阅读不方便而且加载速度慢。

这时候,就需要对这些内容进行分页处理。

Django自身已经集成了一个分页器,不要我们重新造轮子,直接使用就行。看看下面简单的示例代码:

from django.core.paginator import Paginator  #导入分页器
from blog.models import Blog  #自己的模型对象

blogs = Blog.objects.all()  #获取全部博文
pages = Paginator(blogs, 10) #每10个博文对象分为1页

#分页器相关的方法和属性
print pages.count  #得到里面总共有多少个模型对象
print pages.num_pages #总页数
print pages.page_range #页面列表,可以拿来遍历得到全部页码

#得到第1页包含的模型对象,该对象集合可以用于遍历得到里面的模型对象
blogs_page = pages.page(1) 
print blogs_page.number #得到该对象集合当前是哪一页
print blogs_page.has_previous() #判断是否有前一页
print blogs_page.has_next() #判断是否有后一页


有了这些方法之后,我们就可以进一步开发这个分页器的功能了。当然,这些我也记不住,都是用dir得到Paginator里面的方法,一个一个分析的。

之前我的博文列表页面的响应方法大致如下(只写出关键部分):

from blog.models import Blog

def index(request):
    """show blogs' list"""
    data = {}
    blogs = Blog.objects.all()
    data["blogs"] = blogs
    return render_to_response('blog/blog_list.html',data)

加入分页器,修改成如下代码:

from blog.models import Blog
from django.core.paginator import Paginator

def index(request):
    """show blogs' list"""
    data = {}
    #获取GET请求的参数,得到当前页码。若没有该参数,默认为1
    current_page = request.GET.get("page", 1)
    
    blogs = Blog.objects.all()
    pages = Paginator(blogs, 7) #7个对象为1页,这个参数可以写在settings.py里面
    blogs = pages.page(current_page) #获得当前页的数据
    
    data["blogs"] = blogs
    date["pages"] = pages
    return render_to_response('blog/blog_list.html',data)

修改对应的html模版页面如下:

{# 博文之前的就照常加载,这部分我只是简单写出来,略过,重点是分页部分 #}
{% for blog in blogs %}
    {{blog.caption}}
    {# 过滤掉HTML标签和处理HTML转义,输出前100个字符 #}
    {{blog.content|striptags|safe|truncatechars:100}}
{% endfor %}

{# 分页部分 #}
<div>
    <span class="blog_footer_tip">
        共{{pages.count}}篇博文。当前第{{blogs.number}}页,共{{pages.num_pages}}页
    </span>
    
    <ul class="pagination">
        {# 上一页,这里需要用到has_previous方法判断是否有上一页 #}
        <li>
            <a href="?page=
                {% if blogs.has_previous %}
                    {{blogs.previous_page_number}}
                {% else %}
                    {{blogs.number}}
                {% endif %}
            " aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>

        {# 遍历所有页码 #}
        {% for page in pages.page_range %}
            <li><a href="?page={{page}}">{{page}}</a></li>
        {% endfor %}

        {# 下一页,这里需要用到has_next方法判断是否有下一页 #}
        <li>
            <a href="?page=
                {% if blogs.has_next %}
                    {{blogs.next_page_number}}
                {% else %}
                    {{blogs.number}}
                {% endif %}
            " aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    </ul>
</div>

{% block extra_footer %}
    {#设置凸显当前的页码#}
    <script type="text/javascript">
        $(".pagination li:eq({{blogs.number}})").addClass("active");
    </script>
{% endblock %}

ul标签的pagination类是bootstrap的分页器。具体可以参考:http://v3.bootcss.com/components/#pagination

该分页器分为3部分,上一页按钮,全部页面,下一页按钮。

上一页和下一页的页码可以用previous_page_number和next_page_number得到。

不过使用这两个方法之前需要先用has_previous和has_next方法判断。否则若没有对应页码的话,会报错。


这里还写了一段jquery代码,用于凸显当前的页码,让浏览的人可以一下看到当前是属于哪一页的。

最终效果如下:

(前期的文章不是很多,可以直接罗列全部页码处理。先拿出来使用,后面页码多了再进一步处理)


另外,我的网站不止这个地方需要用到分页器。点击标签筛选博文列表的处理方法也需要用到,而且该分页的代码比较相似。可以把这部分代码封装一下,写成一个通用的函数。

from django.core.paginator import Paginator
from django.conf import settings

def getPages(request, objectlist):
    """get the paginator"""
    currentPage = request.GET.get('page', 1)
    
    paginator = Paginator(objectlist, settings.EACHPAGE_NUMBER)
    objectlist = paginator.page(currentPage)

    return paginator, objectlist

在settings.py文件加多了一个EACHPAGE_NUMBER参数,用于设置多少个对象分成1页。

当然名字自己命名即可,自定义的,然后就可以在这里引用并使用。

传递request请求和模型对象集合进来,分页处理之后,再传递回去。

由于这个方法比较通用。我在根目录创建了一个文件夹helper,加了__init__.py文件(这样才会把这个文件夹识别为包,可被引用)。

把这个方法单独放到一个py文件中,文件名为paginator.py。原blog列表的方法则改成:

from blog.models import Blog
from helper.paginator import getPages  #导入helper文件夹的分页通用方法

def index(request):
    """show blogs' list"""
    data = {}
    #获取GET请求的参数,得到当前页码。若没有该参数,默认为1
    current_page = request.GET.get("page", 1)
    
    blogs = Blog.objects.all()
    pages, blogs = getPages(request, blogs) #分页处理
    
    data["blogs"] = blogs
    date["pages"] = pages
    return render_to_response('blog/blog_list.html',data)


哈哈,这样就简单完成了分页功能。(后面文章多了导致页码变多,可再继续拓展完善:我的网站搭建(第22天) 分页器优化

上一篇:我的网站搭建(第4天) 忙?懒?细节优化

下一篇:我的网站搭建(第2天) 博客应用

评论列表

ysh

ysh

评论测试

2015-12-18 09:36 回复

新的评论

清空

猜你喜欢

  • 猜测中,请稍等...