Flask Web 开发 博客文章_3

来源:互联网 发布:外汇编程自动交易 编辑:程序博客网 时间:2024/06/06 07:38

继续上一篇章,分页显示的问题

上一章节讲的是生成了虚拟的用户和文章

这里继续讲分页


这里需要修改app/main/views.py函数

@main.route('/',methods=['GET','POST'])def index():form = PostForm()if current_user.can(Permission.WRITE_ARTICLES) and form.validate_on_submit():post = Post(body = form.body.data,author = current_user._get_current_object())db.session.add(post)return redirect(url_for('.index'))page = request.args.get('page', 1, type=int)pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],error_out=False)posts = pagination.itemsreturn render_template('index.html',form = form, posts = posts, pagination = pagination)


page是通过查询字符串字典里面是否有'page'要求来生成对应的变量page,比如,你的url后面查询字符串里面page=11,那就是要求浏览11页

如果没有,就默认从第一页开始浏览,type=int这句我没理解,我也没查到get方法有第三个参数可选?不过看书上的字面意思是,当从page这个key取值取出来的内容无法转化成证书时候,就使用默认参数,也就是1.


渲染的页数从请求的查询字符串(request.args)中获取,如果没有明确指定,则默认渲染第一页。参数type=int 保证参数无法转换成整数时,返回默认值。
为了显示某页中的记录,要把all() 换成Flask-SQLAlchemy 提供的paginate() 方法。页数是paginate() 方法的第一个参数,也是唯一必需的参数。可选参数per_page 用来指定
每页显示的记录数量;如果没有指定,则默认显示20 个记录。另一个可选参数为error_out,当其设为True 时(默认值),如果请求的页数超出了范围,则会返回404 错误;如果设为False,页数超出范围时会返回一个空列表。为了能够很便利地配置每页显示的记录数量,参数per_page 的值从程序的环境变量FLASKY_POSTS_PER_PAGE 中读取。
这样修改之后,首页中的文章列表只会显示有限数量的文章。若想查看第2 页中的文章,要在浏览器地址栏中的URL 后加上查询字符串?page=2

-----------------------------------------------------------------------------插播源码----------------------------------------------------------------------------------------------------

看到request.args.get('page',1,type=int)这句,甚是不理解,get方法不是只有2个参数,key和default么,怎么会有第三个参数

思路一直在dict的get方法里面找办法,但是找了半天全是只有2个参数的

后来其他筒子给我提醒找找request.args.get这个方法

后来去看了源码,发现args这个是个MultiDict,不是普通字典,而且他的get方法也确实不一样,具体方法如下

就是他会通过第三个参数设置的类型,将第一个参数取到的值转化成该类型,如果转换失败,则返回默认值,官方文档的例子很好地说明了第三个参数的用法


而关于MultiDict这个字典是什么意思,先留个坑位,不展开讲了

#

# 留给MultiDict

#






-----------------------------------------------------------------------------结束插播-------------------------------------------------------------------------------------------


首先是要创建一个宏html文件,以便其他页面导入使用,这个宏文件的主题内容就是设置分页导航

app/templates/_macros.html

{% macro pagination_widget(pagination,endpoint) %}<ul class='pagination'><li {% if not pagination.has_prev %} class='disabled'{% endif %}><a href ="{% if pagination.has_prev %}{{url_for(endpoint,page=pagination.page-1,**kwargs)}}{% else %}#{%endif%}">«</a></li>{% for p in pagination.iter_pages() %}{% if p %}{% if p==pagination.page %}<li class="active"><a href="{{ url_for(endpoint,page=p,**kwargs) }}">{{p}}</a></li>{% else %}<li><a href="{{ url_for(endpoint,page=p,**kwargs) }}">{{p}}</a></li>{% endif %}{% else %}<li class="disabled"><a href="#">…</a></li>{% endif %}{% endfor %}<li{% if not pagination.has_next %} class="disabled"{% endif %}><a href="{% if pagination.has_next %}{{ url_for(endpoint,page = pagination.page+1,**kwargs) }}{% else %}#{% endif %}">»</a></li></ul>{% endmacro %}

一步一步来讲

首先是

{% macro pagination_widget(pagination,endpoint) %}

建立宏文件macro,其实和设置函数是一样的,这里的pagination_widget是函数名,后面括号内的是传入的参数


随后设置一个class类名是pagination的ul类

下面开始设置条件

{% if not pagination.has_prev %} 这句,在这之前,还需要再详细讲一下这个分页如何实现的先后顺序,自己理解的


首先,pagination 是 paginate方法通过Post.query查询出来的分页方法,paginate的第一个参数就是page参数,也就是用户指定要看第几页,但是,当你第一次访问的时候,就是默认的第一页,因为你的request里面是去到达这个整体页面(比如你点击了profile,是导向到profile这个页面)。

而pagination这个类对象,又通过per_page=current_app.config['FLASKY_POSTS_PER_PAGE']这个语句,来进行了分页,比如,每页显示20的话,他分成了6页。

那在最下面的导航栏,就会有1,2,3,4,5,6这样的超链接,你再点击2,3,4,5,6时候,就会有page在request里面

关于request里面的查询字符串,这个感觉要补的东西太多,先挖个坑后面补吧

#

# 留给查询字符串

#

if判断语句 对应的<li>,他并不是page的数字,而是对应的最左边的箭头也就是prevpage功能,相应的在最右边也会有一个箭头,对应的nextpage功能


{% if not pagination.has_prev %} 对当前页面进行判断

所以,如果你是在第一页的话,因为没有前一页了,所以,会把最左边的箭头,禁用了,也就是class=disable见下图1

反之,如果你的当前面也,有前一页的,那么,他会在url后面加上查询字符串,见下图2






接着第二句

<a href ="{% if pagination.has_prev %}{{url_for(endpoint,page=pagination.page-1,**kwargs)}}{% else %}#{%endif%}">&laquo;

注意一下这里的红色字体部分,page-1,就是当前页面号码减去1,这就是左箭头的作用,比如我当前页面是在第三页,那按左箭头应该是导向第二页,如下图

同理,右箭头的作用方式也是如此

另外,超链接最后的显示字符 &laquo;  是表示左箭头,而&raquo;  则表示右箭头,具体的HTML特殊字符,可以参照下面链接


http://www.sjyhome.com/html/html-special-characters.html





接着分析代码

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

一个迭代器,返回一个在分页导航中显示的页数列表。这个列表的最左边显示left_edge 页,当前页的左边显示left_current 页,当前页的右边显示right_current 页,
最右边显示right_edge 页。例如,在一个100 页的列表中,当前页为第50 页,使用默认配置,这个方法会返回以下页数:1、2、None、48、49、50、51、52、53、54、
55、None、99、100。None 表示页数之间的间隔


那也就是说,如果迭代出来的页面就是当前的页面的话,会有一个特殊效果,也就是如上面几个画面中显示的,深色底色。
如果不是当前页面的话,他就少一个深色底色,其他都一样


{% else %}
<li class="disabled"><a href="#">&hellip;</a></li>
除了这些,也就是除了left_edge的2页,left_current的2页,right_current的5页,还有right_edge的2页,其他的显示都应该是&hellip; 这个特殊字符,而这个特殊字符的显示符号,是...  三个点,而这3个点的class是disable,是无法点击的,对应的连接地址也是"#"。






最后,右边的箭头和左边的箭头设置方法是一样的,就不重复了。

然后在相对应的,有posts模板的地方,首先要引入macro,第二个再应用
比如在index.html
{% import "_macros.html" as macros %}...{% include "_posts.html" %}<div class="pagination">{{ macros.pagination_widget(pagination,'.index') }}</div>{% endif %}

以及在user.html里面
{% include "_posts.html" %}<div class="pagination">{{ macros.pagination_widget(pagination,'.user',username = user.username) }}</div>{% endif %}
这里注意,在引入到user里面的时候,记得要把变量username一起传进去

Jinja2 宏的参数列表中不用加入**kwargs 即可接收关键字参数。分页宏把接收到的所有关键字参数都传给了生成分页链接的url_for() 方法

注意这里红色字体部分,在url_for后面的参数,都会被传入url_for的构成里面,也就是说,变量会被传入进去作为url_for的一部分,非常重要




0 0
原创粉丝点击