蓝图和视图

    Blueprint 是一种组织一组相关视图及其他代码的方式。与把视图及其他 代码直接注册到应用的方式不同,蓝图方式是把它们注册到蓝图,然后在工厂函数中 把蓝图注册到应用。

    Flaskr 有两个蓝图,一个用于认证功能,另一个用于博客帖子管理。每个蓝图的代码 都在一个单独的模块中。使用博客首先需要认证,因此我们先写认证蓝图。

    这里创建了一个名称为 'auth' 的 。和应用对象一样, 蓝图需要知道是在哪里定义的,因此把 __name__ 作为函数的第二个参数。 url_prefix 会添加到所有与该蓝图关联的 URL 前面。

    使用 app.register_blueprint() 导入并注册 蓝图。新的代码放在工厂函数的尾部返回应用之前。

    flaskr/__init__.py

    1. def create_app():
    2. app = ...
    3. # existing code omitted
    4. from . import auth
    5. app.register_blueprint(auth.bp)
    6. return app

    认证蓝图将包括注册新用户、登录和注销视图。

    第一个视图:注册

    当用访问 /auth/register URL 时, register 视图会返回用于填写注册 内容的表单的 HTML 。当用户提交表单时,视图会验证表单内容,然后要么再次 显示表单并显示一个出错信息,要么创建新用户并显示登录页面。

    现在只是编写视图代码,在下一页会编写生成 HTML 表单的模板。

    flaskr/auth.py

    这个 register 视图做了以下工作:

    1. 关联了 URL /registerregister 视图函数。当 Flask 收到一个指向 /auth/register 的请求时就会调用 register 视图并把其返回值作为响应。

    2. 如果用户提交了表单,那么 request.method 将会是 'POST' 。这咱情况下 会开始验证用户的输入内容。

    3. 验证 username 和 不为空。

    4. 用户数据保存后将转到登录页面。 根据登录视图的名称生成相应的 URL 。与写固定的 URL 相比, 这样做的好处是如果以后需要修改该视图相应的 URL ,那么不用修改所有涉及到 URL 的代码。 redirect() 为生成的 URL 生成一个重定向响应。

    5. 如果验证失败,那么会向用户显示一个出错信息。 用于储存在渲染模块时可以调用的信息。

    6. 当用户最初访问 auth/register 时,或者注册出错时,应用显示一个注册 表单。 render_template() 会渲染一个包含 HTML 的模板。你会在教程的下一节 学习如何写这个模板。

    这个视图和上述 register 视图原理相同。

    flaskr/auth.py

    1. @bp.route('/login', methods=('GET', 'POST'))
    2. def login():
    3. if request.method == 'POST':
    4. username = request.form['username']
    5. password = request.form['password']
    6. db = get_db()
    7. error = None
    8. user = db.execute(
    9. 'SELECT * FROM user WHERE username = ?', (username,)
    10. ).fetchone()
    11. if user is None:
    12. elif not check_password_hash(user['password'], password):
    13. error = 'Incorrect password.'
    14. if error is None:
    15. session.clear()
    16. session['user_id'] = user['id']
    17. return redirect(url_for('index'))
    18. flash(error)
    19. return render_template('auth/login.html')

    register 有以下不同之处:

    1. 首先需要查询用户并存放在变量中,以备后用。

      根据查询返回一个记录行。 如果查询没有结果,则返回 None 。后面还用到 fetchall() ,它返回包括所有结果的列表。

    2. 是一个 dict ,它用于储存横跨请求的值。当验证 成功后,用户的 id 被储存于一个新的会话中。会话数据被储存到一个 向浏览器发送的 cookie 中,在后继请求中,浏览器会返回它。 Flask 会安全对数据进行 签名 以防数据被篡改。

    现在用户的 id 已被储存在 中,可以被后续的请求使用。 请每个请求的开头,如果用户已登录,那么其用户信息应当被载入,以使其可用于 其他视图。

    flaskr/auth.py

    bp.before_app_request() 注册一个 在视图函数之前运行的函数,不论其 URL 是什么。 load_logged_in_user 检查用户 id 是否已经储存在 中,并从数据库中获取用户数据,然后储存在 g.user 中。 的持续时间比请求要长。 如果没有用户 id ,或者 id 不存在,那么 g.user 将会是 None

    注销

    注销的时候需要把用户 id 从 中移除。 然后 load_logged_in_user 就不会在后继请求中载入用户了。

    flaskr/auth.py

    1. @bp.route('/logout')
    2. def logout():
    3. session.clear()
    4. return redirect(url_for('index'))

    用户登录以后才能创建、编辑和删除博客帖子。在每个视图中可以使用 装饰器 来完成这个工作。

    flaskr/auth.py

    装饰器返回一个新的视图,该视图包含了传递给装饰器的原视图。新的函数检查用户 是否已载入。如果已载入,那么就继续正常执行原视图,否则就重定向到登录页面。 我们会在博客视图中使用这个装饰器。

    端点和 URL

    函数根据视图名称和发生成 URL 。视图相关联的名称亦称为 端点 ,缺省情况下,端点名称与视图函数名称相同。

    例如,前文被加入应用工厂的 hello() 视图端点为 'hello' ,可以使用 url_for('hello') 来连接。如果视图有参数,后文会看到,那么可使用 url_for('hello', who='World') 连接。

    当使用蓝图的时候,蓝图的名称会添加到函数名称的前面。上面的 login 函数 的端点为 'auth.login' ,因为它已被加入 蓝图中。

    下面请阅读 模板