步骤6:视图函数

现在数据库连接已经正常工作,我们终于可以开始写视图函数了。 你一共需要写四个:

显示条目

这个视图显示数据库中存储的所有条目。 它绑定在应用的根地址,并从数据库查询出文章的标题和正文。 id 值最大的条目(最新的条目)会显示在最上方。 从光标返回的行看有点像词典因为我们正在使用sqlite3.Row行工厂函数。

视图函数会将条目作为字典传递给show_entries.html模板,并返回渲染结果:

@app.route('/')
def show_entries():
    db = get_db()
    cur = db.execute('select title, text from entries order by id desc')
    entries = cur.fetchall()
    return render_template('show_entries.html', entries=entries)

添加新条目

这个视图允许已登入的用户添加新条目。它并只响应POST请求;实际的表单显示在show_entries页。 如果一切工作正常,我们会用 flash() 向下 一次请求发送提示消息,并重定向回 show_entries 页:

@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    db = get_db()
    db.execute('insert into entries (title, text) values (?, ?)',
                 [request.form['title'], request.form['text']])
    db.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('show_entries'))

注意,这个视图检查用户是否登入(即,如果logged_in键在会话中存在,并且为True)。

安全提示

确保像上面例子中一样,使用问号标记来构建 SQL 语句。 否则,当你使用格式化字符串构建 SQL 语句时,你的应用容易遭受 SQL 注入。 更多请见 在 Flask 中使用 SQLite 3

登入和登出

这些函数用来让用户登入登出。 登入通过与配置文件中的数据比较检查用户名和密码, 并设定会话中的 logged_in 键值。 如果用户成功登入,那么这个键值会被设为True,并从定向回show_entries页。 此外,会有消息闪现来提示用户登入成功。 如果发生一个错误,模板会通知,并提示重新登录。

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            flash('You were logged in')
            return redirect(url_for('show_entries'))
    return render_template('login.html', error=error)

logout函数,做相反的事情,从会话中删除这个键。我们这里使用了一个简洁的方法:如果你使用字典的pop()方法并传入第二个参数(默认), 这个方法会从字典中删除这个键,如果这个键不存在则什么都不做。 这很有用,因为 我们不需要检查用户是否已经登入。

@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))

安全提示

永远不要把密码以明文形式存储在生产系统中。为简单起见,本教程使用纯文本密码。如果你计划发布基于本教程的项目,密码应该在存储到数据库或文件之前散列和加盐

幸运的是,有Flask扩展用于哈希密码和验证密码的哈希值,因此添加此功能是相当简单的。也有许多可以用于哈希的一般 python 库。

你可以在这里找到推荐的一个Flask扩展列表。

继续步骤7:模板