九、闪现
1、flask闪现的理解
一个好的基于GUI的应用程序会向用户提供有关交互的反馈。例如,桌面应用程序使用对话框或消息框,JavaScript使用警报用于类似目的。在Flask Web应用程序中生成这样的信息性消息很容易。Flask框架的闪现系统可以在一个视图中创建消息,并在名为next的视图函数中呈现它。例如:如果你正在登陆一个网站,当输入用户名、密码并提交后,服务器会受到一个POST请求,当在验证时,发现用户名或密码错误,怎么才能将这个错误信息传回去呢?就是使用Flask的闪现系统,当验证发现用户名或密码错误时,我们可以在session里面设置一个错误信息,然后会返回到填写表单的页面,在浏览器发送GET请求时,我们可以使用session.pop将这个错误信息渲染在login.html里面,使用户知道自己输入的哪些信息不正确。
2、flash使用
app.py
1 from flask import Flask, render_template, flash, get_flashed_messages, request, session, redirect 2 3 4 app = Flask(__name__) 5 6 app.secret_key = "aedvfdvdqfve123e3er31e" 7 8 9 @app.route("/login", methods=["GET", "POST"]) 10 def login(): 11 if request.method == "GET": 12 return render_template("login.html") 13 else: 14 username = request.form.get("username") 15 password = request.form.get("password") 16 if not (username == "admin" and password == "123456"): 17 flash("用户名或密码错误", "login_error") 18 return redirect("/login") 19 session["username"] = username 20 session["password"] = password 21 flash("登陆成功", "login_success") 22 return redirect("/admin") 23 24 25 @app.route("/admin") 26 def admin(): 27 return render_template("admin.html") 28 29 30 if __name__ == '__main__': 31 app.run("localhost", 80, debug=True)
login.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Login</title> 6 </head> 7 <body> 8 <form action="" method="post"> 9 <p><input type="text" placeholder="User:" name="username"></p> 10 <p><input type="password" placeholder="Password:" name="password"></p> 11 <p><input type="file" name="files"></p> 12 {% with messages = get_flashed_messages() %} 13 {% if messages %} 14 <span> 15 {% for message in messages %} 16 {{ message }} 17 {% endfor %} 18 </span> 19 {% endif %} 20 {% endwith %} 21 <p><input type="submit" value="submit"></p> 22 </form> 23 </body> 24 </html>
admin.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>admin</title> 6 </head> 7 <body> 8 {% with messages = get_flashed_messages() %} 9 {% if messages or session.get("username") %} 10 <h1>{{ messages[0] }}欢迎{{ session.get("username") }}</h1> 11 {% else %} 12 <h1><a href="/login">请登录</a></h1> 13 {% endif %} 14 {% endwith %} 15 </body> 16 </html>
3、flash实现机制(flash其实是在session维护了一个键名为_flashes的列表,列表的元素是元组类型,(category, message))
# 第一次请求时,设置 flask("用户名或密码错误", "login_error") # 下一次请求时,获取并销毁 messages = get_flashed_messages() # 列表
使用session实现
# 第一次请求时,设置 session["login_error"] = "用户名或密码错误" # 下一次请求时,获取并销毁 session.pop("login_error"]
源码:
1 def flash(message, category="message"): 2 """Flashes a message to the next request. In order to remove the 3 flashed message from the session and to display it to the user, 4 the template has to call :func:`get_flashed_messages`. 5 6 .. versionchanged:: 0.3 7 `category` parameter added. 8 9 :param message: the message to be flashed. 10 :param category: the category for the message. The following values 11 are recommended: ``'message'`` for any kind of message, 12 ``'error'`` for errors, ``'info'`` for information 13 messages and ``'warning'`` for warnings. However any 14 kind of string can be used as category. 15 """ 16 # Original implementation: 17 # 18 # session.setdefault('_flashes', []).append((category, message)) 19 # 20 # This assumed that changes made to mutable structures in the session are 21 # always in sync with the session object, which is not true for session 22 # implementations that use external storage for keeping their keys/values. 23 flashes = session.get("_flashes", []) 24 flashes.append((category, message)) 25 session["_flashes"] = flashes 26 message_flashed.send( 27 current_app._get_current_object(), message=message, category=category 28 ) 29 30 31 def get_flashed_messages(with_categories=False, category_filter=()): 32 """Pulls all flashed messages from the session and returns them. 33 Further calls in the same request to the function will return 34 the same messages. By default just the messages are returned, 35 but when `with_categories` is set to ``True``, the return value will 36 be a list of tuples in the form ``(category, message)`` instead. 37 38 Filter the flashed messages to one or more categories by providing those 39 categories in `category_filter`. This allows rendering categories in 40 separate html blocks. The `with_categories` and `category_filter` 41 arguments are distinct: 42 43 * `with_categories` controls whether categories are returned with message 44 text (``True`` gives a tuple, where ``False`` gives just the message text). 45 * `category_filter` filters the messages down to only those matching the 46 provided categories. 47 48 See :ref:`message-flashing-pattern` for examples. 49 50 .. versionchanged:: 0.3 51 `with_categories` parameter added. 52 53 .. versionchanged:: 0.9 54 `category_filter` parameter added. 55 56 :param with_categories: set to ``True`` to also receive categories. 57 :param category_filter: whitelist of categories to limit return values 58 """ 59 flashes = _request_ctx_stack.top.flashes 60 if flashes is None: 61 _request_ctx_stack.top.flashes = flashes = ( 62 session.pop("_flashes") if "_flashes" in session else [] 63 ) 64 if category_filter: 65 flashes = list(filter(lambda f: f[0] in category_filter, flashes)) 66 if not with_categories: 67 return [x[1] for x in flashes] 68 return flashes