flask_分页

1、提交博客文章html

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

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

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

 1 {% extends "base.html" %}
 2 {% block content %}
 3 <h1>Hi, {{user.nickname}}!</h1>
 4 <form action="" method="post" name="post">
 5     {{form.hidden_tag()}}
 6     <table>
 7         <tr>
 8             <td>Say something:</td>
 9             <td>{{ form.post(size = 30, maxlength = 140) }}</td>
10             <td>
11             {% for error in form.errors.post %}
12                 <span style="color: red;">[{{error}}]</span><br>
13             {% endfor %}
14             </td>
15         </tr>
16         <tr>
17             <td></td>
18                 <td><input type="submit" value="Post!"></td>
19             <td></td>
20         </tr>
21     </table>
22 </form>
23 {% for post in posts %}
24     {% include 'post.html' %}
25 {% endfor %}

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

 1 from form import LoginForm,EditForm,PostForm
 2 @app.route('/')
 3 @login_required
 4 def index():
 5     user=g.user
 6     form=PostForm()
 7     from model import Post
 8     from model import db
 9     if form.validate_on_submit():
10         post=Post(body=form.post.data,timestamp=datetime.utcnow(),user_id=user.id)
11         db.session.add(post)
12         db.session.commit()
13         flash('Your post is now live!')
14         return redirect(url_for('index'))
15     posts=user.followed_posts()
16     print "posts:",posts
17     return render_template('index.html',title='home',form=form,user=user,posts=posts)

注:这里咱们解释一下为何要重定向到首页(index)app

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

2、分页post

Flask-SQLAlchemy 天生就支持分页。好比说咱们想要在第一页显示前三条blog,咱们能够这么作:ui

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

paginate 方法可以被任何查询调用。它接受三个参数:spa

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):

 1 @app.route('/index<int:page>',methods=['GET','POST'])
 2 @login_required
 3 def index(page=1):
 4     user=g.user
 5     form=PostForm()
 6     from model import Post
 7     from model import db
 8     if form.validate_on_submit():
 9         post=Post(body=form.post.data,timestamp=datetime.utcnow(),user_id=user.id)
10         db.session.add(post)
11         db.session.commit()
12         flash('Your post is now live!')
13         return redirect(url_for('index'))
14     posts=user.followed_posts().paginate(page,POSTS_PER_PAGE,False).items
15     # print "posts:",posts
16     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):

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

所以,咱们有了两个连接。第一个就是名为 “Newer posts”,这个连接使得咱们可以访问上一页。第二个就是 “Older posts”,它指向下一页。

3、修改用户信息页

(1)microblog.py

 1 @app.route('/user/<nickname>')
 2 @app.route('/user/<nickname>/<int:page>')
 3 @login_required
 4 def user(nickname,page=1):
 5     user =model.User.query.filter_by(nickname = nickname).first()
 6     posts=user.posts.paginate(page,POSTS_PER_PAGE,False)
 7     if user == None:
 8         flash('User ' + nickname + ' not found.')
 9         return redirect(url_for('index'))
10     return render_template('user.html',
11         user = user,
12         posts = posts)

(2)user.html

1 {% for post in posts.items %}
2     {% include 'post.html' %}
3 {% endfor %}
4 {% if posts.has_prev %}<a href="{{ url_for('user', nickname = user.nickname, page = posts.prev_num) }}"><< Newer posts</a>{% else %}<< Newer posts{% endif %} |
5 {% if posts.has_next %}<a href="{{ url_for('user', nickname = user.nickname, page = posts.next_num) }}">Older posts >></a>{% else %}Older posts >>{% endif %}
相关文章
相关标签/搜索