一、提交博客文章

1.定义一个单字段的表单对象(form.py)

 class PostForm(Form):
post = StringField('post', validators=[DataRequired()])

2.把表单添加到模板中:(templates/user.html)

 {% extends "base.html" %}
{% block content %}
<h1>Hi, {{user.nickname}}!</h1>
<form action="" method="post" name="post">
{{form.hidden_tag()}}
<table>
<tr>
<td>Say something:</td>
<td>{{ form.post(size = 30, maxlength = 140) }}</td>
<td>
{% for error in form.errors.post %}
<span style="color: red;">[{{error}}]</span><br>
{% endfor %}
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Post!"></td>
<td></td>
</tr>
</table>
</form>
{% for post in posts %}
{% include 'post.html' %}
{% endfor %}

3.利用视图函数来处理表单

 from form import LoginForm,EditForm,PostForm
@app.route('/')
@login_required
def index():
user=g.user
form=PostForm()
from model import Post
from model import db
if form.validate_on_submit():
post=Post(body=form.post.data,timestamp=datetime.utcnow(),user_id=user.id)
db.session.add(post)
db.session.commit()
flash('Your post is now live!')
return redirect(url_for('index'))
posts=user.followed_posts()
print "posts:",posts
return render_template('index.html',title='home',form=form,user=user,posts=posts)

注:这里我们解释一下为什么要重定向到首页(index)

如果一个用户正在撰写 blog,接着不小心按到了浏览器的刷新键,会发生些什么。刷新的命令将会做些什么?浏览器将会重新发送上一次的请求作为刷新命令的结果。没有重定向,上一次的请求是提交表单的 POST 请求,因此刷新动作将会重新提交表单,导致与第一个相同的第二个 Post 记录被写入数据库。这并不好。有了重定向,我们迫使浏览器在表单提交后发送另外一个请求,即重定向页的请求。这是一个简单的 GET 请求,因此一个刷新动作将会重复 GET 请求而不是多次提交表单。

二、分页

Flask-SQLAlchemy 天生就支持分页。比如说我们想要在第一页显示前三条blog,我们可以这么做:

posts=user.followed_posts().paginate(1, 3, False).items

paginate 方法能够被任何查询调用。它接受三个参数:

1.页数,从1开始

2.每一页显示的blog数目

3.错误标志。如果是 True,当请求的范围页超出范围的话,一个 404 错误将会自动地返回到客户端的网页浏览器。如果是 False,返回一个空列表而不是错误。

从 paginate 返回的值是一个 Pagination 对象。这个对象的 items 成员包含了请求页面项目(本文是指 blog)的列表。在 Pagination 对象中还有其它有帮助的东西,我们将在后面能看到。

现在让我们想想如何在我们的 index 视图函数中实现分页。我们首先在配置文件中添加一些决定每页显示的 blog 数的配置项(文件 config.py):

# 每页显示的blog数
POSTS_PER_PAGE = 3

接着,让我们看看不同页的 URLs 是什么样的。我们知道 Flask 路由可以携带参数,因此我们在 URL 后添加一个后缀表示所需的页面:

http://localhost:5000/         <-- page #1 (default)
http://localhost:5000/index <-- page #1 (default)
http://localhost:5000/index/1 <-- page #1
http://localhost:5000/index/2 <-- page #2

这种格式的 URLs 能够轻易地通过在我们的视图函数中附加一个 route 来实现(文件microblog.py):

 @app.route('/index<int:page>',methods=['GET','POST'])
@login_required
def index(page=1):
user=g.user
form=PostForm()
from model import Post
from model import db
if form.validate_on_submit():
post=Post(body=form.post.data,timestamp=datetime.utcnow(),user_id=user.id)
db.session.add(post)
db.session.commit()
flash('Your post is now live!')
return redirect(url_for('index'))
posts=user.followed_posts().paginate(page,POSTS_PER_PAGE,False).items
# print "posts:",posts
return render_template('index.html',title='home',form=form,user=user,posts=posts)

我们新的路由需要页面数作为参数,并且声明为一个整型。同样我们也需要在 index 函数中添加 page 参数,并且我们需要给它一个默认值。

现在我们已经有可用的页面数,我们能够很容易地把它与配置中的 POSTS_PER_PAGE 一起传入 followed_posts 查询。

现在试试输入不同的 URLs,看看分页的效果。但是,需要确保可用的 blog 数要超过三个,这样你就能够看到不止一页了!

4.在页面中添加导航(index.html)

在我们目前的版本中我们按如下方式使用 paginate 方法:

posts=user.followed_posts().paginate(page,POSTS_PER_PAGE,False).items

通过上面这样做,我们可以获得返回自 paginate 的 Pagination 对象的 items 成员。但是这个对象还有很多其它有用的东西在里面,因此我们还是使用整个对象(文件microblog.py):

posts=user.followed_posts().paginate(page,POSTS_PER_PAGE,False)

修改模板index.html

这个改变使得模版能够使用完全的 Paginate 对象。我们使用的这个对象的成员有:

(1)has_next:如果在目前页后至少还有一页的话,返回 True

(2)has_prev:如果在目前页之前至少还有一页的话,返回 True

(3)next_num:下一页的页面数

(4)prev_num:前一页的页面数

有了这些元素后,我们产生了这些(文件 app/templates/index.html):

 {% for post in posts.items %}
{% include 'post.html' %}
{% endfor %}
{% if posts.has_prev %}<a href="{{ url_for('index', page = posts.prev_num) }}"><< Newer posts</a>{% else %}<< Newer posts{% endif %} |
{% if posts.has_next %}<a href="{{ url_for('index', page = posts.next_num) }}">Older posts >></a>{% else %}Older posts >>{% endif %}
{% endblock %}

因此,我们有了两个链接。第一个就是名为 “Newer posts”,这个链接使得我们能够访问上一页。第二个就是 “Older posts”,它指向下一页。

三、修改用户信息页

(1)microblog.py

 @app.route('/user/<nickname>')
@app.route('/user/<nickname>/<int:page>')
@login_required
def user(nickname,page=1):
user =model.User.query.filter_by(nickname = nickname).first()
posts=user.posts.paginate(page,POSTS_PER_PAGE,False)
if user == None:
flash('User ' + nickname + ' not found.')
return redirect(url_for('index'))
return render_template('user.html',
user = user,
posts = posts)

(2)user.html

 {% for post in posts.items %}
{% include 'post.html' %}
{% endfor %}
{% if posts.has_prev %}<a href="{{ url_for('user', nickname = user.nickname, page = posts.prev_num) }}"><< Newer posts</a>{% else %}<< Newer posts{% endif %} |
{% if posts.has_next %}<a href="{{ url_for('user', nickname = user.nickname, page = posts.next_num) }}">Older posts >></a>{% else %}Older posts >>{% endif %}

flask_分页的更多相关文章

  1. 记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题

    最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且在翻第二页的时候也是要这么多的时间,这肯定是不能接受的,也是让现场用SQLServerP ...

  2. js实现前端分页页码管理

    用JS实现前端分页页码管理,可以很美观的区分页码显示(这也是参考大多数网站的分页页码展示),能够有很好的用户体验,这也是有业务需要就写了一下,还是新手,经验不足,欢迎指出批评! 首先先看效果图: 这是 ...

  3. JdbcTemplate+PageImpl实现多表分页查询

    一.基础实体 @MappedSuperclass public abstract class AbsIdEntity implements Serializable { private static ...

  4. MVC如何使用开源分页插件shenniu.pager.js

    最近比较忙,前期忙公司手机端接口项目,各种开发+调试+发布现在几乎上线无问题了:虽然公司项目忙不过在期间抽空做了两件个人觉得有意义的事情,一者使用aspnetcore开发了个人线上项目(要说线上其实只 ...

  5. NET Core-TagHelper实现分页标签

    这里将要和大家分享的是学习总结使用TagHelper实现分页标签,之前分享过一篇使用HtmlHelper扩展了一个分页写法地址可以点击这里http://www.cnblogs.com/wangrudo ...

  6. 套用JQuery EasyUI列表显示数据、分页、查询

    声明,本博客从csdn搬到cnblogs博客园了,以前的csdn不再更新,朋友们可以到这儿来找我的文章,更多的文章会发表,谢谢关注! 有时候闲的无聊,看到extjs那么肥大,真想把自己的项目改了,最近 ...

  7. php实现的分页类

    php分页类文件: <?php /** file: page.class.php 完美分页类 Page */ class Page { private $total; //数据表中总记录数 pr ...

  8. C#关于分页显示

    ---<PS:本人菜鸟,大手子还请高台贵手> 以下是我今天在做分页时所遇到的一个分页显示问题,使用拼写SQL的方式写的,同类型可参考哦~ ------------------------- ...

  9. JAVA 分页工具类及其使用

    Pager.java package pers.kangxu.datautils.common; import java.io.Serializable; import java.util.List; ...

随机推荐

  1. MFC 关于MFC中CImage的简单使用

    首先要将#include <atlimage.h>加进来,开始时我加到stdafx.h中,但一直提示windows.h被重复引入的问题,后将其加在别的头文件中,就可以了..   --! 一 ...

  2. Excel 读写程序 C#源代码下载

    http://u.163.com/lNaJAjOz  提取码: E4ZHjnfD

  3. 转 夕甲甲:孔乙己之 C++ 版

    欧欧匹代码的格局,是和别的编程模式不同的:首先要有一个构造函数:基类里只定义了函数的形式,可以随时通过派生增加不同的实现.那些程序员们,每每学会了继承和多态,便可以接一个项目,——这是十年前的事,现在 ...

  4. chrome调试hove等类似事件

    前台开发过程中经常会用chrome调试代码.但是有的时候,hover或者js控制的属性显示不全 解决办法有两种: 1.根据chrome版本不一样(检查两个字)可能会有所差别 2.图中有标记

  5. 初学c# -- 学习笔记(三)

    结合前面学的许多东西,写了一个小程序.会话.自定义滚动条.css等等.小程序没有用数据库,主要不知道该用哪种,以后再说吧.登录也简单,就输入用户名就可以了. 百度是个好东西,写程序时候,需要什么图就直 ...

  6. shell脚本中的反引号使用 `

    反引号是~的英文切换 在shell脚本中,反引号允许将shell命令的输出赋值给变量. test=`date` 这样shell会执行反引号中的命令.并将执行的结果赋值给变量tests.

  7. Tomcat 7.x热部署

    由于在开发阶段,需要频繁的修改源代码,如果每次修改完代码都去重启服务器来检测效果,那简直麻烦到你想死,又耽误时间,所以,在网上找了许久,终于找到了解决办法, 特来分享 我也试了修改Server.xml ...

  8. Visio 2007中进行数据库建模时如何显示字段类型以及概念名称

    关于在VISIO中进行数据库建模时如何显示字段类型,以及注释的 1 如何显示字段类型:   在visio菜单上--->点击数据库--->选项--->文档    打开后选择表这项,在上 ...

  9. NSArray转json字符串

    func arrayToJson(arr:NSArray) -> String { let jsonData: NSData = try! NSJSONSerialization.dataWit ...

  10. Android Studio线下版和线上版都使用正式签名脚本(保证keysore签名文件和项目在同级目录),不用再因为繁琐的发正式版而烦恼

    场景:调用微信等第三方应用时如果生成的版本不是正式签名的可能会调用失败,使用如下脚本不用再为繁琐的发正式签名版而烦恼 app项目中的build.gradle追加如下代码: //使用正式签名脚本(保证k ...