Django开发博客(十)—添加分页
来源:互联网 发布:精雕雕刻机编程教程 编辑:程序博客网 时间:2024/04/29 05:03
背景
我的博客上线也有一段时间了,非常稳定的运行了那么久,我也写了挺多文章。
那么问题来了,文章多了,我们并没有做分页,随着文章越来越多,整个页面看起来就不是那么舒服了,所以现在我需要给我的博客做一个分页。
版本相关
操作系统:Mac OS X EI Caption
Python版本:2.7
IDE:PyCharm
分页的原理
Django是一个非常全面的Web框架,也预置了分页的功能,《Django中文文档-分页》比较详细的介绍了Django的分页功能。
然而,我并不想按照Django给的分页功能来做。学习一个东西最好学习它的本质。
分页的原理其实很简单,就是根据你传入的参数从数据库获取一部分的数据来展示。比如按照5篇文章来分页,每次就从数据库取5条数据,然后返回给前端展示即可。
url的修改
我们要对原有的url进行一个简单的修改。修改后的url是这样的:
url(r'^list/(?P<list_type>\S+)/(?P<page>[0-9]+)/$', views.article_list, name='article_list'),
比起原来的url,这里多传了一个参数page。这个page就是用来标记我们的页码,比如第一页数据,这个page就填1,然后后台接受这个page后从数据库去第一条至第五条数据返回给前端。第二页就传2,以此类推。
views的修改
url做了修改,那么views也要做一些修改来接收这个page。
def article_list(request, list_type, page): page = int(page) pages = [x for x in range(1, get_pages(list_type) + 1)] end = pages[-1] content_list = BlogBody.objects.filter(blog_type=list_type).order_by('-blog_timestamp')[(page - 1) * 8: page * 8] print page if get_pages(list_type) > 1: return render(request, 'blog/article_list.html', {'content_list': content_list, 'list_type': list_type, 'pages': pages, 'end': end, 'page': page, 'errmsg': 'OK'}) else: return render(request, 'blog/article_list.html', {'content_list': content_list, 'list_type': list_type, 'pages': pages, 'end': end, 'errmsg': 'faile'})
views的修改基本上是整个分页的核心。我详细的说明一下。
page = int(page)
先把传入的page转换成int类型,方便后续做数学计算。如果不做转换,在python2.7中是unicode类型,无法执行计算。
pages = [x for x in range(1, get_pages(list_type) + 1)]
这里专门做一个pages的列表,是用来给前端迭代生成分页页码的,当然Django也可以用loop的方式来生成,我觉得在后台能处理的就一起处理了,前端只负责展示,不进行不必要的计算。
end = pages[-1]
这个赋值是吧最后一页的页码返回给前端。
content_list = BlogBody.objects.filter(blog_type=list_type).order_by('-blog_timestamp')[(page - 1) * 8: page * 8]
这句就是一个查询的逻辑,也是分页的重点,前面是筛选和按时间戳排序,重点关注最后一个。我这里是按每页8篇文章来分页,那么传入的page为1的时候,我就要取【0:8】的数据来展示,传入2的时候,我就要取【8:16】的数据来展示,这个计算方式就确保了每次传入的page都会去后台取对应的记录。
if get_pages(list_type) > 1: return render(request, 'blog/article_list.html', {'content_list': content_list, 'list_type': list_type, 'pages': pages, 'end': end, 'page': page, 'errmsg': 'OK'}) else: return render(request, 'blog/article_list.html', {'content_list': content_list, 'list_type': list_type, 'pages': pages, 'errmsg': 'faile'})def get_pages(list_type): num = divmod(BlogBody.objects.filter(blog_type=list_type).count(), 8) if num[1] != 0: pages = num[0] + 1 else: pages = num[0] return pages
这段逻辑就判断是做一个简单的处理,首先通过查询逻辑确定一共有几页,如果只有一页,那么前端就不展示分页的数据,如果大于1页,那么就把分页的页码展示出来。
前端修改
前端要针对后台的修改做一些针对性的修改.
base.html
base.html文件里面的很多url跳转,由于url新增了一个参数,那么也要对应的加上这个参数。
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="{% url 'article_list' 'python' '1'%}">Python</a></li> <li><a href="{% url 'article_list' 'test' '1'%}">有关测试</a></li> <li><a href="{% url 'article_list' 'mytalk' '1'%}">个人杂谈</a></li> <li><a href="{% url 'article_list' 'diary' '1'%}">日记</a></li> <li><a href="{% url 'message' %}">留言板</a></li> <li role="presentation" class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"> 寒彬小数据 <span class="caret"></span> </a> <ul class="dropdown-menu"> <li><a href="{% url 'film' %}">实时票房</a></li> <li><a href="{% url 'weather' %}">天气资讯</a></li> </ul> </li> </ul> <form class="navbar-form navbar-right" role="search"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">搜索</button> </form></div>
为page参数默认赋值为1的逻辑是因为点击某个分类后,肯定是进入这个分类的第一页。
article_list.html
这个文件的修改同样是最重要的部分。代码如下:
{% if errmsg == 'OK' %} <nav> <ul class="pagination pagination-lg"> <li> <a href="{% url 'article_list' list_type '1' %}" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% for p in pages %} {% if page == p %} <li class="active"><a href="{% url 'article_list' list_type p %}">{{ p }}</a></li> {% else %} <li><a href="{% url 'article_list' list_type p %}">{{ p }}</a></li> {% endif %} {% endfor %} <li id="end"> <a href="{% url 'article_list' list_type end %}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav> {% endif %}
首先判断errmsg。如果页码大于2,那么后台传的errmsg的值就是OK。这个时候我们才需要进行分页,否则不显示分页。
获取到OK之后,我们要在前端展示页码。分页信息一般由这么几部分组成:
- 第一页和最后一页
- 中间的页码
<li> <a href="{% url 'article_list' list_type '1' %}" aria-label="Previous"> <span aria-hidden="true">«</span> </a></li>
上面的代码就是处理第一页的逻辑。代码是直接从bootstrap的官网copy下来的,使用的是首页的默认图标,当然也可以自行修改文字。
<li id="end"> <a href="{% url 'article_list' list_type end %}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li>
之前在views文件中我返了一个end字段。就用来填到最后一页的地方。
{% for p in pages %} {% if page == p %} <li class="active"><a href="{% url 'article_list' list_type p %}">{{ p }}</a></li> {% else %} <li><a href="{% url 'article_list' list_type p %}">{{ p }}</a></li> {% endif %} {% endfor %}
上面代码就是生成中间页码部分的代码。有几个地方要注意的。
迭代获取数据,然后生成页码,这个没有上面大问题。
我们必须告诉浏览网页的人当前页是第几页,当然url中有,但是在页面中有的话更好咯。所以在views中我专门把url中的页码返回给前端,当然用js也是可以处理的,我整了一遍,发现用Django直接处理更方便。if的逻辑就是当迭代的页码等于当前页码的时候,给当前的li标签加上一个active的class。
最后
我只记录了一些功能的流程,还有很多异常的处理读者可以自行脑补,比如访问者手工输入了不存在的页码要怎么处理。
最后放上效果图
- Django开发博客(十)—添加分页
- Django开发博客(六)——添加markdown支持
- Django博客开发(九)—添加多说评论和JS日历
- Django个人博客开发(十:lblog/models.py lblog/index.html、十一:lsite index.html)
- django 个人博客系统开发 - 最新文章获取和分页
- Django开发博客(四)——建立文章列表
- Django开发博客(五)——新增文章
- Django开发博客(七)——markdown优化
- Django开发博客(八)——部署在SAE
- Django博客开发(十三)—一个简单的站内搜索
- django开发电子商城(三)django内置分页
- Django 学习小组:博客开发实战第三周教程——文章列表分页和代码语法高亮
- Django个人博客开发
- Django后台添加博客文章
- Django开发博客-(1)Django简介
- 用flask开发个人博客(36)—— 使用SQLAlchemy对博客文章进行分页
- 利用Django快速开发博客
- django开发博客(1) 入门
- bzoj4515【SDOI2016】游戏
- bugly上报与umeng的区别
- mysql group by 用法解析(详细) from xxpyeippx
- gluOrtho2D() 结合glViewport() 的使用
- 在VS中配置OpenCV
- Django开发博客(十)—添加分页
- javamail邮箱发送
- BeanDefinition在IOC容器中的注册
- Leetcode 69. Sqrt(x) 开根号 解题报告
- Windows网络编程学习笔记(3) 编写一个TCP服务端
- c++primer plus 第八章习题答案(自己写的)
- 配置redis外网可访问
- DIV和ID、class是什么
- X Window System配置