Python的Flask框架中实现分页功能的教程
|
Blog Posts的提交 让我们从简单的开始。首页上必须有一张用户提交新的post的表单。 首先我们定义一个单域表单对象(fileapp/forms.py):
class PostForm(Form):
post = TextField('post',validators = [Required()])
下面,我们把这个表单添加到template中(fileapp/templates/index.html):
<!-- extend base layout -->
{% extends "base.html" %}
{% block content %}
<h1>Hi,{{g.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 %}
<p>
{{post.author.nickname}} says: <b>{{post.body}}</b>
</p>
{% endfor %}
{% endblock %}
到目前为止没啥新的东西,你可以看到,我们仅仅添加了另一表单,就像我们上一次做的那样。 最后,功能试图把所有东西都联系在一起,并被扩展来处理这个表单(fileapp/views.py):
from forms import LoginForm,EditForm,PostForm
from models import User,ROLE_USER,ROLE_ADMIN,Post
@app.route('/',methods = ['GET','POST'])
@app.route('/index','POST'])
@login_required
def index():
form = PostForm()
if form.validate_on_submit():
post = Post(body = form.post.data,timestamp = datetime.utcnow(),author = g.user)
db.session.add(post)
db.session.commit()
flash('Your post is now live!')
return redirect(url_for('index'))
posts = [
{
'author': { 'nickname': 'John' },'body': 'Beautiful day in Portland!'
},{
'author': { 'nickname': 'Susan' },'body': 'The Avengers movie was so cool!'
}
]
return render_template('index.html',title = 'Home',form = form,posts = posts)
下面让我们逐一回顾一下这个功能中的变动:
在我们继续之前还有最后一点提醒:注意下面我们如何添加一条新的Post请求到数据库中:
return redirect(url_for('index'))
我们可以很容易的跳过重定向,并且允许它跳到模板渲染部分,而且效率更高。因为所做的所有重定向在经过web浏览器之后,都返回到这个相同的功能视图中来。 所以,为什么选择重定向?考虑到当用户写下一个blog post请求之后,它只需提交然后点击浏览器刷新按钮。“Refresh”命令能做什么呢?浏览器会重新发送最后发布的请求作为一个“Refresh”命令的结果。(译者注:由于个人水平有限,如果您发现译处与原文有出入敬请指正。谢谢!)
若是有了重定向,我们可以强制浏览器在表单提交之后发出另一个请求,它抓取了重定向的页面。这是一个简单的“GET”请求,所以“Refresh”动作会重复“GET”请求而不是再次提交表单。 这个简单的小技巧避免用户在提交一个blog post请求之后,不小心刷新页面导致重复写入post请求。 展现blog post请求 下面我们来说点有意思的东西。我们要从数据库中抓取blog post请求并失之显示。 如果你回忆一下之前部分文章,我们曾创建了许多所谓“虚假的”的请求并且在首页上面显示了很长时间。这些“虚假的”对象是作为Python list在索引视图中创建的。
posts = [
{
'author': { 'nickname': 'John' },'body': 'The Avengers movie was so cool!'
}
]
但是在上一篇文章中,我们创建的查询语句允许我们从“关注的人”当中获取所有的请求,所以我们可以用下面的这个语句来替换上文(fileapp/views.py): posts = g.user.followed_posts().all() 然后当你运行这个应用的时候,你将会看到冲数据库中抓取到的bolg post请求。
此时您可以在此应用上自由发挥。你可以创建多个用户,让他们follow其他人,然后发布一些信息来看每一个用户是如何看到它的bolg post请求数据流的。 分页
我们可以显示把这么大量的post分组来显示,或者分页。 Flask-SQLAlchemy可以很好的支持分页。例如,我们可以通过如下方法,轻松获取某个用户的前3篇的followed posts: posts = g.user.followed_posts().paginate(1,3,False).items 分页方法可以被任何query对象调用。它接受3个参数:
paginate的返回值是一个Pagination对象。这个对象里面的成员包括了请求页面中的记录列表。稍后,我们会探讨Pagination对象中另外一些有用的东西。 现在让我们来想想,如何在我们的view函数中实现分页。我们可以先把一些配置信息添加到我们的应用中,包括我们每页需要显示多少条记录(fileconfig.py): # pagination POSTS_PER_PAGE = 3 使用全局配置文件去改变我们应用是一个很好的构思,因为我们只需要去一个地方就可以修改所有的配置。 在最后的应用中,我们当然会使用比3更大的数字,但是作为测试,使用小的数字会更有效。 之后,让我们来看看URLs是如何判断请求不同的页面的。我们之前已知道,Flask的routes可以接受参数的,所以我们可以在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到我们的view函数当中(fileapp/views.py):
from config import POSTS_PER_PAGE
@app.route('/','POST'])
@app.route('/index/<int:page>','POST'])
@login_required
def index(page = 1):
form = PostForm()
if form.validate_on_submit():
post = Post(body = form.post.data,author = g.user)
db.session.add(post)
db.session.commit()
flash('Your post is now live!')
return redirect(url_for('index'))
posts = g.user.followed_posts().paginate(page,POSTS_PER_PAGE,False).items
return render_template('index.html',posts = posts)
我们的新route接受分页参数,并把参数定义为整数。我们还需要添加分页参数到index函数当中,并给它们一个默认值,因为那三个route当中有两个route没有分页参数,所以这些route就必须用到默认值。
我们可以注意到,这些更改是如何的简单,并且当我们更改一个页面的时候,很少代码会被影响。我们尝试在写应用中的每个部分的时候,不去假设其他部分是如何的工作,这样就会让我们写出模块化的和健壮的应用,使得测试更简单,而且更少的出错机会,或者缺陷。 现在你可以尝试在你的浏览器地址栏中,在URLs中输入页码。请确保你的pots超过3个,这样你就可以看到多个页面。 页面导航 现在我们需要添加链接,好让我们的用户可以查看上一个/下一个页面,很幸运,这个功能很容易实现,Flask-SQLAlchemy给我们完成了大部分的工作。 我们现在给view函数更改一小部分代码。我们在paginate方法中修改: posts = g.user.followed_posts().paginate(page,False).items (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
