上章的结束,若在实际开发过程中,会发现一个问题,那就首页或关注分享,是一下子按时间顺序全部显示出来,这在实际项目中不可能出现的,想想实际中的产品是如何做的?

一般来说,无非是两种,一种是使用页码,来进行分页,还有一种是js到页底自动加载,而使用页底自动加载的话,上一章实现的通过tab来区分全部和关注就不可取了,因为无法保证两个tab加载的内容数量一致,导致页面布局就无法实现,所以,这里首页参考tumblr的实现方式,删除关注分享的部分,只保留全部分享,使用js页底动态加载分页方式,同时在导航栏新增两个导航,分别为博文,和关注,使用传统页码的方式显示全部博文和已关注博文,这样是为了有些人可能会查询比较久的历史信息,所以,一个页面,一个功能如何设计,主要取决于业务需求,而不是技术需求。首先修改导航(base.html):

  • 首页
  • 分享

{% if current_user.is_authenticated %}

aria-haspopup="true" aria-expanded="false">关注

  • 分享
  • 用户

{% endif %}

用户登录后,在首页后面会新增两个item,分别是分享和关注,其中关注是一个下拉菜单,分别是“我”关注的用户发布的分享,和“我”关注的用户

下面完成这几个页面,首先是分享页,即所有用户发布的分享,页面与之前的首页很像,首先完成视图模型:

@main.route("/post")

@main.route("/post/")

def post(page=1):

pagination=Post.query.order_by(Post.createtime.desc()).paginate(

page,per_page=current_app.config["POSTS_PER_PAGE"],error_out=False

)

return render_template("posts.html",posts=pagination.items,pagination=pagination,endpoint=request.endpoint)

这个模型的route的意思是,既可以通过/post访问,也可以通过/post/1等类型访问,当/post访问的时候,默认访问第一页。

endpoint的意思为访问的端点,即方法的端点,针对于这个方法来说,endpoint的值为"main.post"

接下来的内容,就是本章的一个重点了,pagination对象,这个是flask-SQLAlchemy框架中的一个很重要的对象,它包含了一系列用于分页的属性,其中主要的属性如下:

has_next

是否还有下一页

has_prev

是否还有前一页

items

当前页的数据

iter_pages(left_edge=2,left_current=2,right_current=5,right_edge=2)

一个关于页面的迭代,可以有四个带有默认值的参数:

left_edge 页码最左边显示的页数

left_current 当前页左边显示的页数

right_current 当前页右边显示的页数

right_edge 页面最右边显示的页数

可能有些不好理解,举个例子,假设共100页,当前为50页,则显示如下:

1,2...48,49,50,51,52,53,54,55...99,100

next(error_out=False)

下一页的分页对象,当error_out为true时,超过页面返回404

prev(error_out=False)

上一页的分页对象

page

当前页码

prev_num

上页页码

next_num

下页页码

per_page

每页显示的记录数量

total

记录总数

还有更多属性,请查验文档

分享页的模板与首页几乎一样,同样是一个分享发布框,一个已分享列表(posts.html):

{% import "_index_post_macros.html" as macros %}...

{% if current_user.is_authenticated %}{{ wtf.quick_form(form) }}{% endif %}

{{macros.rander_posts(posts,moment,pagination,endpoint)}}

{% if current_user.is_authenticated %}

我已经分享{{ current_user.posts.count() }}条心情

我已经关注了{{ current_user.followed.count() }}名好友

我已经被{{ current_user.followers.count() }}名好友关注

{%endif%}

{% endblock %}{% block scripts %}{{ super() }}{{ pagedown.include_pagedown() }}

e.preventDefault()

$(this).tab('show')

})

{% endblock%}

并没有做过多的封装,其实完全可以把右侧在封装成为一个macro

接下来是_index_post_macros.html

{% macro rander_posts(posts,moment,pagination=None,endpoint=None) %}{% import "_posts_page_macros.html" as macros %}{% for post in posts %}

{% if post.body_html%}{{post.body_html|safe}}{% else %}{{post.body}}{% endif %}

{{post.author.nickname}}

发表于 {{ moment( post.createtime).fromNow(refresh=True)}}

{% endfor %}{% if pagination and endpoint %}{{macros.rander_page(pagination,endpoint)}}{% endif %}{%endmacro%}

这里需要注意的一点也就是最下边新增的代码,意味着macro也可以嵌套,如果pagination和endpoint不为None,则显示页码,而_posts_page_macros.html的代码如下:

{% macro rander_page(pagination,endpoint) %}

{% if pagination.has_prev %}

«

{% else %}

«

{% endif %}{% for p in pagination.iter_pages() %}{% if p%}{% if p ==pagination.page%}

{{p}}

{% else %}

{{p}}

{% endif %}{% else %}

...

{% endif %}{% endfor %}{% if pagination.has_next %}

»

{% else %}

»

{% endif %}

{% endmacro %}

这是一个比较典型的pagination的使用方式,完全使用了bootstrap的样式,最终的显示效果如下:

貌似内容有点少,分页我发测试,并且之后关注分页,首页动态分页都要用,所以首先要扩充一些分享内容,扩充的方式多种多样,比如实际数据,手动修改数据库,但对于python来说,它提供了一个不错的生成虚拟数据的轮子,即ForgeryPy,首先当然还是安装:

pip3.6 install ForgeryPy

然后修改Post类,添加一个静态方法(Post.py)

@staticmethod

def generate_fake():

from random import seed, randint;

from .User import User

import forgery_py;

seed()

user_count = User.query.count()

for i in range(100):

u = User.query.offset(randint(0, user_count - 1)).first()

p = Post(body=forgery_py.lorem_ipsum.sentences(randint(1, 3)),

createtime=forgery_py.date.date(True), author=u)

db.session.add(p)

db.session.commit()

几个参数说明一下:

lorem_ipsum比较有趣,原意为一些排版时的占位用的无意义字符,具体解释可参考阮博的博客,sentences方法为生成普通句子,参数代表句子的数量。

date的参数表示生成时间的区间,True表示生成的区间都为过去的时间

这个静态方法的使用方式为:

python manage.py shell

Post.generate_fake()

这样就会生成100条分享。

下面在看一下分享页的效果(尾页):

不考虑美工的话,效果还是可以的,不过内容都是英文的,不知道能不能有一个中文的虚拟数据生成器:)

下面是关注分享页,和这个页类似,视图模型为:

@main.route("/follow_post",methods=["GET","POST"])

@main.route("/follow_post/",methods=["GET","POST"])

@login_required

def follow_post(page=1):

form = PostForm()

if form_util(form):

return redirect(url_for(request.endpoint)) # 跳回首页

print(form.body.data)

pagination=Post.query.select_from(Follow).filter_by(follower_id=current_user.id)\

.join(Post,Follow.followed_id == Post.author_id).paginate(

page,per_page=current_app.config["POSTS_PER_PAGE"],error_out=False

)

return render_template("posts.html",posts=pagination.items,form=form,

pagination=pagination,endpoint=request.endpoint)

注意,由于关注分享,分享和首页都有PostForm,所以把这个功能独立出来:

def form_util(form):

if form.validate_on_submit():

post = Post(body=form.body.data, author_id=current_user.id)

db.session.add(post);

return True

return False

其实我想flask应该有整个页面的某一个功能独立为一个视图模型的方式,但我没有找到,如果读者找到了别忘了留言回复

最后,关注的用户就太简单了,可以直接使用某用户关注的页面,将userid参数赋予当前用户的参数即可,最终base.html的导航部分代码为:

  • 首页
  • 分享

{% if current_user.is_authenticated %}

aria-haspopup="true" aria-expanded="false">关注

  • 分享
  • 用户

{% endif %}

{% if current_user.is_authenticated %}

{{current_user.username}} 您好

登出

{% else %}

登录注册

{% endif %}

搜索

然后删除首页中tab的部分,最终代码为:

{% if current_user.is_authenticated %}{{ wtf.quick_form(form) }}{% endif %}

  • 最新分享

{{macros.rander_posts(posts,moment)}}

{% if current_user.is_authenticated %}

我已经分享{{ current_user.posts.count() }}条心情

我已经关注了{{ current_user.followed.count() }}名好友

我已经被{{ current_user.followers.count() }}名好友关注

{%endif%}

这时候,你可能已经发现了,首页的分享还没有进行分页,在本章的开始部分就已经解释道,首页使用动态加载的分页方式,而动态加载显然需要js的配合,使用json的方式向html中注入。这时候服务端就会面临一个问题,如何与客户端的js进行交互呢,这是下一章将要说明的问题。

python对列表进行分页_python列表分页相关推荐

  1. python中append的用法_Python 列表 append() 使用方法及示例

    Python 列表 append() 使用方法及示例 append()方法将一个项目添加到列表的末尾. append()方法将单个项目添加到列表的末尾. append()方法的语法为:list.app ...

  2. python列表字典操作_Python 列表(list)、字典(dict)、字符串(string)常用基本操作小结...

    创建列表 sample_list = ['a',1,('a','b')] Python 列表操作 sample_list = ['a','b',0,1,3] 得到列表中的某一个值 value_star ...

  3. python字典下标是什么_python列表、元组、字典

    1.列表 列表是由一序列特定顺序排列的元素组成的.可以把字符串,数字,字典等都可以任何东西加入到列表中,列表中的元素之间没有任何关系.列表也是自带下标的,默认也还是从0开始.列表常用方括号表示,即:[ ...

  4. python列表浅复制_Python列表深浅复制详解

    转自:https://www.cnblogs.com/blaomao/p/7239203.html 在文章<Python 数据类型>里边介绍了列表的用法,其中列表有个 copy() 方法, ...

  5. python处理列表中字典_Python 列表、元组、字典及集合操作详解

    一.列表 列表是Python中最基本的数据结构,是最常用的Python数据类型,列表的数据项不需要具有相同的类型 列表是一种有序的集合,可以随时添加和删除其中的元素 列表的索引从0开始 1.创建列表 ...

  6. python列表添加元组_python 列表与元组的操作简介

    列表 列表是可变的(mutable)--可以改变列表的内容,这不同于字符串和元组,字符串和元组都是不可变的.接下来讨论一下列表所提供的方法. list函数 可以使用list函数来创建列表: list( ...

  7. python列表求平均数_python 列表平均值

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我有一个列表:类似: data = , , , ] 我想把这个算出来... 我想 ...

  8. python列表比较方法_python列表常用方法

    list是一个类,用中括号括上,逗号分隔,元素可以是数字,字符,字符串,也可以是嵌套列表,布尔类型. 1.通过索引取值 li=[1,12,9,'age',['wangtianning',[19,'10 ...

  9. python列表的长度_Python 列表/数组(list)长度不足自动补零(补齐元素)

    Python 列表/数组(list)长度不足自动补零(补齐元素) 背景: python3.8 一个三元组列表,需要拆成三个独立列表,然后每个列表长度必须满足5位 如:li = [(0, 15, 33) ...

  10. python列表反向排序_Python 列表排序方法reverse、sort、sorted详解

    python语言中的列表排序方法有三个:reverse反转/倒序排序.sort正序排序.sorted可以获取排序后的列表.在更高级列表排序中,后两中方法还可以加入条件参数进行排序. reverse() ...

最新文章

  1. 我的实用设计模式 - Simple Factory和Reflection
  2. Laravel自定义验证规则的实例与框架使用正则实例
  3. Spring boot 定制banner
  4. 20应用统计考研复试要点(part13)--应用多元分析
  5. 图论--二分图最佳完美匹配(KM模板)
  6. 马斯克嘲讽元宇宙:谁会整天戴个头盔?
  7. 网站站长综合seo在线查询工具源码
  8. 【P000-008】交易费计算系统,1.1版
  9. python3扬州大学校园网认证登录与下线
  10. sql server2016中文版
  11. 银行计算机岗位职称,银行职称有哪些,等级是如何划分的
  12. 数学最高奖菲尔兹奖得主加入华为!研究数学大一统理论,任正非曾说“国家若要强盛,数学是基础”...
  13. 台式机和计算机有什么区别,笔记本电脑和台式电脑有什么区别
  14. 小程序学习 - 02 微信小程序案例实践
  15. 【官方文档】Fluent Bit 安装在 Linux
  16. Fater RCNN 试着加入注意力机制模型
  17. 批处理系统脱机使用计算机,1.2.2 脱机输入/输出和批处理系统
  18. 二十、从句_限定性定语从句
  19. 论文阅读-----使用可分离脚印的x射线3D CT向前和向后投影
  20. 开发三年,靠这份Java面试宝典,拿到字节offer

热门文章

  1. DevOps和SRE有什么不同,每个意味着什么
  2. 又是金三银四,都是Java程序员,你为什么面试总拿不到高薪?
  3. shell之常用工具的使用
  4. LiveVideoStackCon 一次全新的尝试,错过了就是一辈子
  5. 刘文峰:让科技成就艺术创意
  6. Java多线程之线程通信之生产者消费者阻塞队列版
  7. python 类的特殊成员(属性和方法)
  8. Android常用开源框架
  9. ubuntu修改mysql的绑定端口
  10. centos7 redis5.0以前版本 部署集群示例 - 第二篇