flask-使用SQLAlchemy对博客文章进行分页

我们在浏览某个博客网站时,如果博客文章过多,往往都进行了分页显示,比如CSDN中个人博客的首页显示。在flask中SQLAlchemy不但可以进行数据建模和数据查询等等,由于其支持分页查询,我们还可以利用其对我们的文章进行分页。

一、创建博客数据模型

        在介绍使用SQLAlchemy对博客进行分页之前,我们需要先创建博客的数据模型,并向数据库中插入试验用的博客的数据。我们将博客的数据模型定义如下:

 
  1. class Post(db.Model):

  2. __tablename__='posts'

  3. id=db.Column(db.Integer,primary_key=True)

  4. body=db.Column(db.Text)

  5. timestamp=db.Column(db.DateTime,index=True,default=datetime.utcnow)

        博客的数据表中只含有3个字段:博客id、博客内容和时间戳,定义完成之后,我们向数据库中插入两个Post对象,以此作为试验数据:

二、定义视图函数,利用SQLAlchemy进行分页查询

        

 
  1. @main.route('/',methods=['GET','POST'])

  2. def index():

  3. page=request.args.get('page',1,type=int)

  4. pagination=Post.query.paginate(page,per_page=1,error_out=False)

  5. posts=pagination.items

  6. return render_template('index.html',posts=posts,pagination=pagination)

        通过request.args.get我们可以获取一个url所带的参数,比如 http://localhost:5000/?page=1 携带参数page,值为1。request.args.get('page',1,type=int)的意思是从request的参数中获取参数page的值,如果参数不存在那么返回默认值1,type=int保证返回的默认值是整形数字。

        SQLAlchemy中查询对象query的paginate方法返回一个分页对象pagination,Post.query.pagination(page,per_page=1,error_out=False)中第一个参数表示我们要查询的页数,这里用了上面获取的url的参数;第二个参数是每页显示的数量,我们这里设置成了1,如果不设置默认显示20条;第3个参数如果设置成True,当请求的页数超过了总的页数范围,就会返回一个404错误,如果设为False,就会返回一个空列表。

        通过上面的分页,如果我们简单在index.html进行如下设置,就可以实现根据不同参数的url显示不同的博客文章:

index.html:

 
  1. {% for post in posts %}

  2. {{ post.body }}

  3. {% endfor %}


url:http://localhost:5000/?page=1

url:http://localhost:5000/?page=2

三、添加分页导航

    上面只是简单根据不同的url参数显示不同的博客文章,在实际应用时我们还需要给分页添加分页导航。paginate()方法返回的Pagination类对象包含很多属性和方法,我们可以利用它的属性和方法实现分页导航。它的属性和方法如下:

属性 说明
items 当前页面的记录
query 分页的源查询
page 当前的页数
prev_num 上一页数
next_num 下一页数
has_prev 是否有上一页
has_next 是否有下一页
pages 总的页数
per_page 每页显示的记录条数
total 总的记录条数
方法 说明
iter_pages
(left_edge=2,
left_current=2,right_current=5,right_age=2)
一个迭代器,返回选中当前页时显示的页数列表。如这个例子中最左边显示2个页数,当前页的左边显示2个页数,当前页的右边显示5个页数而当前页的最右边显示2个页数
prev() 上一页的分页对象
next() 下一页的分页对象


        使用上面的属性和方法,我们可以修改index.html文件,对当前的博客列表实现分页导航:

 
  1. <!DOCTYPE html>

  2. <html>

  3. <head>

  4. <meta charset="utf-8" />

  5. <style type="text/css">

  6. #menu {

  7. font:12px verdana, arial, sans-serif; /* 设置文字大小和字体样式 */

  8. }

  9. #menu, #menu li {

  10. list-style:none; /* 将默认的列表符号去掉 */

  11. padding:0; /* 将默认的内边距去掉 */

  12. margin:0; /* 将默认的外边距去掉 */

  13. }

  14. </style>

  15. <style type="text/css">

  16. #menu li {

  17. float:left; /* 往左浮动 */

  18. }

  19. </style>

  20. <style type="text/css">

  21. #menu li a {

  22. display:block; /* 将链接设为块级元素 */

  23. padding:8px 50px; /* 设置内边距 */

  24. background:#3A4953; /* 设置背景色 */

  25. color:#fff; /* 设置文字颜色 */

  26. text-decoration:none; /* 去掉下划线 */

  27. border-right:1px solid #000; /* 在左侧加上分隔线 */

  28. }

  29. </style>

  30. <title></title>

  31. </head>

  32. <body>

  33. {% for post in posts %}

  34. {{ post.body }}

  35. {% endfor %}

  36. <ul id="menu">

  37. <li>

  38. <a href="{% if pagination.has_prev %}{{url_for('.index',page=pagination.page-1)}}{% else %}#{% endif %}" >«</a>

  39. </li>

  40. {% for p in pagination.iter_pages() %}

  41. <li>

  42. <a href="{{ url_for('.index',page=p)}}">{{p}}</a>

  43. </li>

  44. {% endfor %}

  45. <li>

  46. <a href="{%if pagination.has_next %}{{url_for('.index',page=pagination.page+1)}}{% else %}#{% endif %}" >»</a>

  47. </li>

  48. </ul>

  49.  
  50. </body>

  51. </html>


        我们重点关注li标签中针对pagination的操作,首先根据当前的pagination是否有上一页对a标签进行了不同href的赋值,创建出<<的超链接;与之对应的是在最后根据当前pagination是否有下一页而再次对a标签赋予不同的url,创建出>>超链接;中间调用pagination的迭代器iter_pages(),便利每个分页对象,在以每个分页对象定义不同的超链接。

实现的效果如下:

猜你喜欢

转载自blog.csdn.net/yy19890521/article/details/81289027