Flask 教程,第九部分:分页 已翻译 100%

oschina 投递于 2012/12/28 09:38 (共 20 段, 翻译完成于 01-30)
阅读 18564
收藏 10
1
加载中
红薯
翻译于 2012/12/29 17:25
1

概述

前一篇文章中,我们已经取得了所有必要的支持“跟随”模式,让用户选择其他用户对数据库的修改。

今天,我们将说说上一次我们做了什么,以使我们的应用程序可以接收和发送真实信息给用户。我们今天将对我们最后的虚假消息说再见!

Jasonhoho
翻译于 2012/12/30 13:52
1

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 %}

到目前为止没啥新的东西,你可以看到,我们仅仅添加了另一表单,就像我们上一次做的那样。

Jasonhoho
翻译于 2012/12/30 13:57
1

最后,功能试图把所有东西都联系在一起,并被扩展来处理这个表单(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', methods = ['GET', '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和PostForm类
  • 我们接收了来自两个路径下的index和视图的POST请求,因为那就是我们如何接收提交的请求。
  • 当我们通过表单提交到功能视图后,我们会把新的Post记录录入数据库。然后就像之前做的一样,通过常规的GET请求来访问它。
  • Templat会收到一条额外的内容--表单,所以它会提交给文本域。
Jasonhoho
翻译于 2012/12/30 14:08
1

在我们继续之前还有最后一点提醒:注意下面我们如何添加一条新的Post请求到数据库中:

return redirect(url_for('index'))

我们可以很容易的跳过重定向,并且允许它跳到模板渲染部分,而且效率更高。因为所做的所有重定向在经过web浏览器之后,都返回到这个相同的功能视图中来。

所以,为什么选择重定向?考虑到当用户写下一个blog post请求之后,它只需提交然后点击浏览器刷新按钮。“Refresh”命令能做什么呢?浏览器会重新发送最后发布的请求作为一个“Refresh”命令的结果。(译者注:由于个人水平有限,如果您发现译处与原文有出入敬请指正。谢谢!)

Jasonhoho
翻译于 2012/12/30 16:26
1

如果没有重定向,那么最后提交给表单的就是POST请求,所以一个“Refresh Action”会重新提交那个表单,将会导致第二次提交的post记录和第一次写入数据库中的是相同的。这样的行为Not so good.

若是有了重定向,我们可以强制浏览器在表单提交之后发出另一个请求,它抓取了重定向的页面。这是一个简单的“GET”请求,所以“Refresh”动作会重复“GET”请求而不是再次提交表单。

这个简单的小技巧避免用户在提交一个blog post请求之后,不小心刷新页面导致重复写入post请求。

Jasonhoho
翻译于 2012/12/30 16:37
1

展现blog post请求

下面我们来说点有意思的东西。我们要从数据库中抓取blog post请求并失之显示。

如果你回忆一下之前部分文章,我们曾创建了许多所谓“虚假的”的请求并且在首页上面显示了很长时间。这些“虚假的”对象是作为Python list在索引视图中创建的。

posts = [
        { 
            'author': { 'nickname': 'John' }, 
            'body': 'Beautiful day in Portland!' 
        },
        { 
            'author': { 'nickname': 'Susan' }, 
            'body': 'The Avengers movie was so cool!' 
        }
    ]

但是在上一篇文章中,我们创建的查询语句允许我们从“关注的人”当中获取所有的请求,所以我们可以用下面的这个语句来替换上文(fileapp/views.py):

posts = g.user.followed_posts().all()

然后当你运行这个应用的时候,你将会看到冲数据库中抓取到的bolg post请求。

Jasonhoho
翻译于 2012/12/30 16:47
1

User类的followed_posts方法返回了一条抓取我们感兴趣请求的SQL查询语句。在这个查询语句中,Callingall()检索所有的请求到一个list当中,所以我们以这个很像我们一直沿用至今的“虚假”请求的结构结束。他们如此的相像甚至template都没有注意到。

此时您可以在此应用上自由发挥。你可以创建多个用户,让他们follow其他人,然后发布一些信息来看每一个用户是如何看到它的bolg post请求数据流的。

Jasonhoho
翻译于 2012/12/30 17:06
1

分页


我们的程序是越来越像样了,但是我们面临另外一个问题。我们在首页显示了所有的followed post。如果一个用户有上千篇followed post将会发生什么情况?或者一百万篇?就像我们可以想象到的,抓取并处理这么庞大的对象列表是十分低效率的。

我们可以显示把这么大量的post分组来显示,或者分页。

enixyu
翻译于 2013/01/29 08:52
1

Flask-SQLAlchemy可以很好的支持分页。例如,我们可以通过如下方法,轻松获取某个用户的前3篇的followed posts:

posts = g.user.followed_posts().paginate(1, 3, False).items
分页方法可以被任何query对象调用。它接受3个参数:
  • 页码,从1开始
  • 每页显示的记录数
  • 错误标记。如果是True,如果接收到超出记录范围的页面请求,那么404错误请求将会自动反馈到客户端浏览器。如果是False,那么一个空列表将会被返回,而不显示错误。


enixyu
翻译于 2013/01/29 08:59
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(1)

Jasonhoho
Jasonhoho
放了一天的羊终于下班了,办公室里只剩下个位数的人,明天放假,哈哈。。。待续。
返回顶部
顶部