Flask 学习笔记(二)

第一个Flask 应用

为了测试 Flask 安装,请在编辑器中将以下代码输入 Hello.py:

  1. from flask import Flask
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def hello_world():
  5. return 'Hello World'
  6. if __name__ == '__main__':
  7. app.run()

必须在项目中导入Flask模块。 Flask类的一个对象是我们的WSGI应用程序。

Flask构造函数使用当前模块(name 的名称作为参数。

Flask类的route()函数是一个装饰器,它告诉应用程序哪个URL应该调用相关的函数。

  1. app.route(rule, options)
  • rule 参数表示与该函数的URL绑定。
  • options 是要转发给基础Rule对象的参数列表。

在上面的示例中,’/ ‘ URL与hello_world()函数绑定。因此,当在浏览器中打开web服务器的主页时,将呈现该函数的输出。

最后,Flask类的run()方法在本地开发服务器上运行应用程序。

  1. app.run(host, port, debug, options)

所有参数都是可选的

序号 参数与描述
1 host 要监听的主机名。 默认为127.0.0.1(localhost)。设置为“0.0.0.0”以使服务器在外部可用
2 port 默认值为5000
3 debug 默认为false。 如果设置为true,则提供调试信息
4 options 要转发到底层的Werkzeug服务器。

上面给出的Python脚本是从Python shell执行的。

  1. Python Hello.py

Python shell中的消息通知您:

  1. * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

在浏览器中打开上述URL(localhost:5000)。将显示“Hello World”消息。

这里注意,如果使用python自带的idle运行的时候可能会报以下错误:

  1. Traceback (most recent call last):
  2. File C:/learn/python/xuexi/web/demoflask/app.py”, line 27, in
  3. app.run();
  4. File C:\Users\zhang\AppData\Local\Programs\Python\Python36\lib\site-packages\flask\app.py”, line 938, in run
  5. cli.show_server_banner(self.env, self.debug, self.name, False)
  6. File C:\Users\zhang\AppData\Local\Programs\Python\Python36\lib\site-packages\flask\cli.py”, line 629, in show_server_banner
  7. click.echo(message)
  8. File C:\Users\zhang\AppData\Local\Programs\Python\Python36\lib\site-packages\click\utils.py”, line 217, in echo
  9. file = _default_text_stdout()
  10. File C:\Users\zhang\AppData\Local\Programs\Python\Python36\lib\site-packages\click_compat.py”, line 621, in func
  11. rv = wrapper_func()
  12. File C:\Users\zhang\AppData\Local\Programs\Python\Python36\lib\site-packages\click_compat.py”, line 385, in get_text_stdout
  13. rv = _get_windows_console_stream(sys.stdout, encoding, errors)
  14. File C:\Users\zhang\AppData\Local\Programs\Python\Python36\lib\site-packages\click_winconsole.py”, line 261, in _get_windows_console_stream
  15. func = _stream_factories.get(f.fileno())
  16. io.UnsupportedOperation: fileno

只要不用idle执行就不会出错了,不影响后续使用。改用cmd下Python执行或者pycharm等运行都能成功。

调试模式

通过调用run()方法启动Flask应用程序。但是,当应用程序正在开发中时,应该为代码中的每个更改手动重新启动它。为避免这种不便,请启用调试支持。如果代码更改,服务器将自行重新加载。它还将提供一个有用的调试器来跟踪应用程序中的错误(如果有的话)。

在运行或将调试参数传递给run()方法之前,通过将application对象的debug属性设置为True来启用Debug模式

  1. app.debug = True
  2. app.run()
  3. app.run(debug = True)

Flask 路由

现代Web框架使用路由技术来帮助用户记住应用程序URL。可以直接访问所需的页面,而无需从主页导航。

Flask中的route()装饰器用于将URL绑定到函数。例如:

  1. @app.route(‘/hello’)
  2. def hello_world():
  3. return hello world

在这里,URL ‘/ hello’ 规则绑定到hello_world()函数。 因此,如果用户访问http:// localhost:5000 / hello URL,hello_world()函数的输出将在浏览器中呈现。

application对象的add_url_rule()函数也可用于将URL与函数绑定,如上例所示,使用route()

装饰器的目的也由以下表示:

  1. def hello_world():
  2. return hello world
  3. app.add_url_rule(‘/’, hello’, hello_world)

Flask 变量规则

通过向规则参数添加变量部分,可以动态构建URL。此变量部分标记为 。它作为关键字参数传递给与规则相关联的函数。

在以下示例中,route()装饰器的规则参数包含附加到URL ‘/hello’ 因此,如果在浏览器中输入http://localhost:5000/hello/w3cschool作为URL,则‘w3cschool’将作为参数提供给 hello()函数。

  1. from flask import Flask
  2. app = Flask(__name__)
  3. @app.route('/hello/<name>')
  4. def hello_name(name):
  5. return 'Hello %s!' % name
  6. if __name__ == '__main__':
  7. app.run(debug = True)

将上述脚本保存为hello.py并从Python shell运行它。接下来,打开浏览器并输入URL http:// localhost:5000/hello/Hello。

以下输出将显示在浏览器中:

  1. Hello Hello!

除了默认字符串变量部分之外,还可以使用以下转换器构建规则:

序号 转换器和描述
1 int接受整数
2 float对于浮点值
3 path 接受用作目录分隔符的斜杠

在下面的代码中,使用了所有这些构造函数:

  1. from flask import Flask
  2. app = Flask(__name__)
  3. @app.route('/blog/<int:postID>')
  4. def show_blog(postID):
  5. return 'Blog Number %d' % postID
  6. @app.route('/rev/<float:revNo>')
  7. def revision(revNo):
  8. return 'Revision Number %f' % revNo
  9. if __name__ == '__main__':
  10. app.run()

从Python Shell运行上面的代码。访问浏览器中的URL http://localhost:5000/blog/11

给定的数字用作show_blog()函数的参数。浏览器显示以下输出:

  1. Blog Number 11

在浏览器中输入此URL - http://localhost:5000/rev/1.1

revision()函数将浮点数作为参数。以下结果显示在浏览器窗口中:

  1. Revision Number 1.100000

Flask的URL规则基于Werkzeug的路由模块。这确保形成的URL是唯一的,并且基于Apache规定的先例。

考虑以下脚本中定义的规则:

  1. from flask import Flask
  2. app = Flask(__name__)
  3. @app.route('/flask')
  4. def hello_flask():
  5. return 'Hello Flask'
  6. @app.route('/python/')
  7. def hello_python():
  8. return 'Hello Python'
  9. if __name__ == '__main__':
  10. app.run()

这两个规则看起来类似,但在第二个规则中,使用斜杠(/)。因此,它成为一个规范的URL。因此,使用 /python/python/返回相同的输出。但是,如果是第一个规则,/flask/ URL会产生“404 Not Found”页面。

Flask URL构建

url_for()函数对于动态构建特定函数的URL非常有用。该函数接受函数的名称作为第一个参数,以及一个或多个关键字参数,每个参数对应于URL的变量部分。

以下脚本演示了如何使用url_for()函数:

  1. from flask import Flask, redirect, url_for
  2. app = Flask(__name__)
  3. @app.route('/admin')
  4. def hello_admin():
  5. return 'Hello Admin'
  6. @app.route('/guest/<guest>')def hello_guest(guest):
  7. return 'Hello %s as Guest' % guest
  8. @app.route('/user/<name>')
  9. def hello_user(name):
  10. if name =='admin':
  11. return redirect(url_for('hello_admin'))
  12. else:
  13. return redirect(url_for('hello_guest',guest = name))
  14. if __name__ == '__main__':
  15. app.run(debug = True)

上述脚本有一个函数user(name),它接受来自URL的参数的值。

User()函数检查接收的参数是否与‘admin’匹配。如果匹配,则使用url_for()将应用程序重定向到hello_admin()函数,否则重定向到将接收的参数作为guest参数传递给它的hello_guest()函数。

保存上面的代码并从Python shell运行。

打开浏览器并输入URL - http://localhost:5000/user/admin

浏览器中的应用程序响应是:

  1. Hello Admin

在浏览器中输入以下URL - http://localhost:5000/user/mvl

应用程序响应现在更改为:

  1. Hello mvl as Guest

Flask HTTP方法

Http协议是万维网中数据通信的基础。在该协议中定义了从指定URL检索数据的不同方法。

下表总结了不同的http方法:

序号 方法与描述
1 GET以未加密的形式将数据发送到服务器。最常见的方法。
2 HEAD和GET方法相同,但没有响应体。
3 POST用于将HTML表单数据发送到服务器。POST方法接收的数据不由服务器缓存。
4 PUT用上传的内容替换目标资源的所有当前表示。
5 DELETE 删除由URL给出的目标资源的所有当前表示。

默认情况下,Flask路由响应GET请求。但是,可以通过为route()装饰器提供方法参数来更改此首选项。

为了演示在URL路由中使用POST方法,首先让我们创建一个HTML表单,并使用POST方法将表单数据发送到URL。

相关文档请参考

Flask 模板

在前面的实例中,视图函数的主要作用是生成请求的响应,这是最简单请求.实际上,视图函数有两个作用:

  • 处理业务逻辑
  • 返回响应内容

在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本.

  • 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
  • 使用真实值替换变量,再返回最终得到的字符串,这个过程称为’渲染’
  • Flask 是使用 Jinja2 这个模板引擎来渲染模板

使用模板的好处

  • 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
  • 而模板则取到视图函数的数据结果进行展示(视图展示方面)
  • 代码结构清晰,耦合度低

模板基本使用

在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件 html 文件 hello.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. 我的模板html内容
  9. </body>
  10. </html>

创建视图函数,将该模板内容进行渲染返回

  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def index():
  5. return render_template('hello.html')

模板变量

代码中传入字符串,列表,字典到模板中

  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def index():
  5. # 往模板中传入的数据
  6. my_str = 'Hello Word'
  7. my_int = 10
  8. my_array = [3, 4, 2, 1, 7, 9]
  9. my_dict = {
  10. 'name': 'xiaoming',
  11. 'age': 18
  12. }
  13. return render_template('hello.html',
  14. my_str=my_str,
  15. my_int=my_int,
  16. my_array=my_array,
  17. my_dict=my_dict
  18. )

模板中代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. 我的模板html内容
  9. <br />{{ my_str }}
  10. <br />{{ my_int }}
  11. <br />{{ my_array }}
  12. <br />{{ my_dict }}
  13. </body>
  14. </html>

运行效果

  1. 我的模板html内容
  2. Hello Word
  3. 10
  4. [3, 4, 2, 1, 7, 9]
  5. {'name': 'xiaoming', 'age': 18}

示例代码

  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def index():
  5. my_int = 18
  6. my_str = 'curry'
  7. my_list = [1, 5, 4, 3, 2]
  8. my_dict = {
  9. 'name': 'durant',
  10. 'age': 28
  11. }
  12. # render_template方法:渲染模板
  13. # 参数1: 模板名称 参数n: 传到模板里的数据
  14. return render_template('hello.html',
  15. my_int=my_int,
  16. my_str=my_str,
  17. my_list=my_list,
  18. my_dict=my_dict)
  19. if __name__ == '__main__':
  20. app.run(debug=True)
  21. <!DOCTYPE html>
  22. <html lang="en">
  23. <head>
  24. <meta charset="UTF-8">
  25. <title>Title</title>
  26. </head>
  27. <body>
  28. <h2>我是模板</h2>
  29. {{ my_int }}
  30. <br>
  31. {{ my_str }}
  32. <br>
  33. {{ my_list }}
  34. <br>
  35. {{ my_dict }}
  36. <hr>
  37. <h2>模板的list数据获取</h2>
  38. <hr>
  39. {{ my_list[0] }}
  40. <br>
  41. {{ my_list.1 }}
  42. <hr>
  43. <h2>字典数据获取</h2>
  44. <hr>
  45. {{ my_dict['name'] }}
  46. <br>
  47. {{ my_dict.age }}
  48. <hr>
  49. <h2>算术运算</h2>
  50. <br>
  51. {{ my_list.0 + 10 }}
  52. <br>
  53. {{ my_list[0] + my_list.1 }}
  54. </body>
  55. </html>

Flask 静态文件

Web应用程序通常需要静态文件,例如javascript文件或支持网页显示的CSS文件。通常,配置Web服务器并为您提供这些服务,但在开发过程中,这些文件是从您的包或模块旁边的static文件夹中提供,它将在应用程序的/static中提供。

特殊端点’static’用于生成静态文件的URL。

在下面的示例中,在index.html中的HTML按钮的OnClick事件上调用hello.js中定义的javascript函数,该函数在Flask应用程序的“/”URL上呈现。

  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. @app.route("/")
  4. def index():
  5. return render_template("index.html")
  6. if __name__ == '__main__':
  7. app.run(debug = True)

index.html的HTML脚本如下所示:

  1. <html>
  2. <head>
  3. <script type = "text/javascript"
  4. src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
  5. </head>
  6. <body>
  7. <input type = "button" onclick = "sayHello()" value = "Say Hello" />
  8. </body>
  9. </html>

Hello.js包含sayHello()函数。

  1. function sayHello() {
  2. alert("Hello World")
  3. }

Flask Request对象

来自客户端网页的数据作为全局请求对象发送到服务器。为了处理请求数据,应该从Flask模块导入。

Request对象的重要属性如下所列:

  • Form - 它是一个字典对象,包含表单参数及其值的键和值对。
  • args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
  • Cookies - 保存Cookie名称和值的字典对象。
  • files - 与上传文件有关的数据。
  • method - 当前请求方法。

Flask 将表单数据发送到模板

我们已经看到,可以在 URL 规则中指定 http 方法。触发函数接收的 Form 数据可以以字典对象的形式收集它并将其转发到模板以在相应的网页上呈现它。

在以下示例中,‘/‘ URL 会呈现具有表单的网页(student.html)。填入的数据会发布到触发 result() 函数的 ‘/result’ URL

result() 函数收集字典对象中的 request.form 中存在的表单数据,并将其发送给 result.html

该模板动态呈现表单数据的 HTML 表格。

下面给出的是应用程序的 Python 代码:

  1. from flask import Flask, render_template, request
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def student():
  5. return render_template('student.html')
  6. @app.route('/result',methods = ['POST', 'GET'])
  7. def result():
  8. if request.method == 'POST':
  9. result = request.form
  10. return render_template("result.html",result = result)
  11. if __name__ == '__main__':
  12. app.run(debug = True)

下面给出的是 student.html 的 HTML 脚本。

  1. <form action="http://localhost:5000/result" method="POST">
  2. <p>Name <input type = "text" name = "Name" /></p>
  3. <p>Physics <input type = "text" name = "Physics" /></p>
  4. <p>Chemistry <input type = "text" name = "chemistry" /></p>
  5. <p>Maths <input type ="text" name = "Mathematics" /></p>
  6. <p><input type = "submit" value = "submit" /></p>
  7. </form>

下面给出了模板( result.html )的代码:

  1. <!doctype html>
  2. <table border = 1>
  3. {% for key, value in result.items() %}
  4. <tr>
  5. <th> {{ key }} </th>
  6. <td> {{ value }}</td>
  7. </tr>
  8. {% endfor %}
  9. </table>

运行 Python 脚本,并在浏览器中输入 URL http://localhost:5000/

Flask 学习笔记(二) - 图1

当点击提交按钮时,表单数据以 HTML 表格的形式呈现在 result.html 上。

Flask 学习笔记(二) - 图2

Flask Cookies

Cookie以文本文件的形式存储在客户端的计算机上。其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和网站统计信息。

Request对象包含Cookie的属性。它是所有cookie变量及其对应值的字典对象,客户端已传输。除此之外,cookie还存储其网站的到期时间,路径和域名。

在Flask中,对cookie的处理步骤为:

\1. 设置cookie:

设置cookie,默认有效期是临时cookie,浏览器关闭就失效

可以通过 max_age 设置有效期, 单位是秒

  1. resp = make_response("success") # 设置响应体
  2. resp.set_cookie("w3cshool", "w3cshool", max_age=3600)

2.获取cookie

获取cookie,通过request.cookies的方式, 返回的是一个字典,可以获取字典里的相应的值

  1. cookie_1 = request.cookies.get("w3cshool")

3.删除cookie

这里的删除只是让cookie过期,并不是直接删除cookie

删除cookie,通过delete_cookie()的方式, 里面是cookie的名字

  1. resp = make_response("del success") # 设置响应体
  2. resp.delete_cookie("w3cshool")

以下为Flask Cookies的简单示例:

  1. from flask import Flask, make_response, request
  2. app = Flask(__name__)
  3. @app.route("/set_cookies")
  4. def set_cookie():
  5. resp = make_response("success")
  6. resp.set_cookie("w3cshool", "w3cshool",max_age=3600) return resp
  7. @app.route("/get_cookies")
  8. def get_cookie():
  9. cookie_1 = request.cookies.get("w3cshool") # 获取名字为Itcast_1对应cookie的值
  10. return cookie_1
  11. @app.route("/delete_cookies")
  12. def delete_cookie():
  13. resp = make_response("del success")
  14. resp.delete_cookie("w3cshool")
  15. return resp
  16. if __name__ == '__main__':
  17. app.run(debug=True)

注意删除,只是让 cookie 过期。

Flask Sessions(会话)

与Cookie不同,Session(会话)数据存储在服务器上。会话是客户端登录到服务器并注销服务器的时间间隔。需要在该会话中保存的数据会存储在服务器上的临时目录中。

为每个客户端的会话分配会话ID。会话数据存储在cookie的顶部,服务器以加密方式对其进行签名。对于此加密,Flask应用程序需要一个定义的SECRET_KEY

Session对象也是一个字典对象,包含会话变量和关联值的键值对。

例如,要设置一个‘username’会话变量,请使用以下语句:

  1. Session[‘username’] = admin

要释放会话变量,请使用pop()方法。

  1. session.pop('username', None)

以下代码是Flask中的会话工作的简单演示。URL ‘/‘只是提示用户登录,因为未设置会话变量‘username’

  1. @app.route('/')
  2. def index():
  3. if 'username' in session:
  4. username = session['username']
  5. return 'Logged in as ' &plus; username &plus; '<br>' &plus; \
  6. "<b><a href = '/logout'>click here to log out</a></b>"
  7. return "You are not logged in <br><a href = '/login'></b>" &plus; \
  8. "click here to log in</b></a>"

当用户浏览到“/login”login()视图函数时,因为它是通过GET方法调用的,所以将打开一个登录表单。

表单发送回‘/login’,现在会话变量已设置。应用程序重定向到‘/‘。此时会话变量‘username’被找到。

  1. @app.route('/login', methods = ['GET', 'POST'])
  2. def login():
  3. if request.method == 'POST':
  4. session['username'] = request.form['username']
  5. return redirect(url_for('index'))
  6. return '''
  7. <form action = "" method = "post">
  8. <p><input type = text name = username/></p>
  9. <p<<input type = submit value = Login/></p>
  10. </form>
  11. '''

应用程序还包含一个logout()视图函数,它会弹出‘username’会话变量。因此,‘/‘ URL再次显示开始页面。

  1. @app.route('/logout')
  2. def logout():
  3. # remove the username from the session if it is there
  4. session.pop('username', None)
  5. return redirect(url_for('index'))

运行应用程序并访问主页。(确保设置应用程序的secret_key

  1. from flask import Flask, session, redirect, url_for, escape, request
  2. app = Flask(__name__)
  3. app.secret_key = 'any random string’

完整代码如下所示

  1. from flask import Flask
  2. from flask import render_template
  3. from flask import request
  4. from flask import make_response
  5. from flask import Flask, session, redirect, url_for, escape, request
  6. app = Flask(__name__)
  7. app.secret_key = 'fkdjsafjdkfdlkjfadskjfadskljdsfklj'
  8. @app.route('/')
  9. def index():
  10. if 'username' in session:
  11. username = session['username']
  12. return '登录用户名是:' + username + '<br>' + \
  13. "<b><a href = '/logout'>点击这里注销</a></b>"
  14. return "您暂未登录, <br><a href = '/login'></b>" + \
  15. "点击这里登录</b></a>"
  16. @app.route('/login', methods = ['GET', 'POST'])
  17. def login():
  18. if request.method == 'POST':
  19. session['username'] = request.form['username']
  20. return redirect(url_for('index'))
  21. return '''
  22. <form action = "" method = "post">
  23. <p><input type ="text" name ="username"/></p>
  24. <p><input type ="submit" value ="登录"/></p>
  25. </form>
  26. '''
  27. @app.route('/logout')
  28. def logout():
  29. # remove the username from the session if it is there
  30. session.pop('username', None)
  31. return redirect(url_for('index'))
  32. if __name__ == '__main__':
  33. app.run(debug = True)

输出将显示如下。点击“点击此处登录”链接。

链接将被定向到另一个屏幕。键入“admin”。

屏幕会显示消息“ 登录用户名是:admin

Flask 重定向和错误

Flask类有一个redirect()函数。调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。

redirect()函数的原型如下:

  1. Flask.redirect(location, statuscode, response)

在上述函数中:

  • location参数是应该重定向响应的URL。
  • statuscode发送到浏览器标头,默认为302。
  • response参数用于实例化响应。

以下状态代码已标准化:

  • HTTP_300_MULTIPLE_CHOICES
  • HTTP_301_MOVED_PERMANENTLY
  • HTTP_302_FOUND
  • HTTP_303_SEE_OTHER
  • HTTP_304_NOT_MODIFIED
  • HTTP_305_USE_PROXY
  • HTTP_306_RESERVED
  • HTTP_307_TEMPORARY_REDIRECT

默认状态代码为302,表示‘found’

在以下示例中,redirect()函数用于在登录尝试失败时再次显示登录页面。

  1. from flask import Flask, redirect, url_for, render_template, request
  2. # Initialize the Flask application
  3. app = Flask(__name__)
  4. @app.route('/')
  5. def index():
  6. return render_template('log_in.html')
  7. @app.route('/login',methods = ['POST', 'GET'])
  8. def login():
  9. if request.method == 'POST' and
  10. request.form['username'] == 'admin' :
  11. return redirect(url_for('success'))
  12. return redirect(url_for('index'))
  13. @app.route('/success')
  14. def success():
  15. return 'logged in successfully'
  16. if __name__ == '__main__':
  17. app.run(debug = True)

Flask类具有带有错误代码的abort()函数。

  1. Flask.abort(code)

Code参数采用以下值之一:

  • 400 - 用于错误请求
  • 401 - 用于未身份验证的
  • 403 - Forbidden
  • 404 - 未找到
  • 406 - 表示不接受
  • 415 - 用于不支持的媒体类型
  • 429 - 请求过多

让我们对上述代码中的login()函数稍作更改。如果要显示‘Unauthurized’页面,请将其替换为调用abort(401),而不是重新显示登录页面。

  1. from flask import Flask, redirect, url_for, render_template, request, abort
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def index():
  5. return render_template('log_in.html')
  6. @app.route('/login',methods = ['POST', 'GET'])
  7. def login():
  8. if request.method == 'POST':
  9. if request.form['username'] == 'admin' :
  10. return redirect(url_for('success'))
  11. else:
  12. abort(401)
  13. else:
  14. return redirect(url_for('index'))
  15. @app.route('/success')
  16. def success():
  17. return 'logged in successfully'
  18. if __name__ == '__main__':
  19. app.run(debug = True)

Flask 消息闪现

一个好的基于 GUI 的应用程序会向用户提供有关交互的反馈。例如,桌面应用程序使用对话框或消息框,JavaScript 使用警报用于类似目的。

在 Flask Web 应用程序中生成这样的信息性消息很容易。Flask 框架的闪现系统可以在一个视图中创建消息,并在名为 next 的视图函数中呈现它。

Flask 模块包含 flash() 方法。它将消息传递给下一个请求,该请求通常是一个模板。

  1. flash(message, category)

其中,

  • message 参数是要闪现的实际消息。
  • category 参数是可选的。它可以是“error”,“info”或“warning”。

为了从会话中删除消息,模板调用 get_flashed_messages()

  1. get_flashed_messages(with_categories, category_filter)

两个参数都是可选的。如果接收到的消息具有类别,则第一个参数是元组。第二个参数仅用于显示特定消息。

以下闪现在模板中接收消息。

  1. {% with messages = get_flashed_messages() %}
  2. {% if messages %}
  3. {% for message in messages %}
  4. {{ message }}
  5. {% endfor %}
  6. {% endif %}
  7. {% endwith %}

让我们看一个简单的例子,演示Flask中的闪现机制。在以下代码中,‘/‘ URL 显示登录页面的链接,没有消息闪现。

  1. @app.route('/')
  2. def index():
  3. return render_template('index.html')

该链接会将用户引导到‘/ login’ URL,该 URL 显示登录表单。提交时,login() 视图函数验证用户名和密码,并相应闪现 ‘success’ 消息或创建 ‘error’ 变量。

  1. @app.route('/login', methods = ['GET', 'POST'])
  2. def login():
  3. error = None
  4. if request.method == 'POST':
  5. if request.form['username'] != 'admin' or \
  6. request.form['password'] != 'admin':
  7. error = 'Invalid username or password. Please try again!'
  8. else:
  9. flash('You were successfully logged in')
  10. return redirect(url_for('index'))
  11. return render_template('login.html', error = error)

如果出现错误,则会重新显示登录模板,并显示错误消息。

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 method = "post" action = "http://localhost:5000/login">
  9. <table>
  10. <tr>
  11. <td>Username</td>
  12. <td><input type = 'username' name = 'username'></td>
  13. </tr>
  14. <tr>
  15. <td>Password</td>
  16. <td><input type = 'password' name = 'password'></td>
  17. </tr>
  18. <tr>
  19. <td><input type = "submit" value = "Submit"></td>
  20. </tr>
  21. </table>
  22. </form>
  23. {% if error %}
  24. <p><strong>Error</strong>: {{ error }}</p>
  25. {% endif %}
  26. </body>
  27. </html>

另一方面,如果登录成功,则会在索引模板上刷新成功消息。

Index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Index</title>
  6. </head>
  7. <body>
  8. {% with messages = get_flashed_messages() %}
  9. {% if messages %}
  10. {% for message in messages %}
  11. <p>{{ message }}</p>
  12. {% endfor %}
  13. {% endif %}
  14. {% endwith %}
  15. <h3>Welcome!</h3>
  16. <a href = "{{ url_for('login') }}">login</a>
  17. </body>
  18. </html>

下面给出了 Flask 消息闪现示例的完整代码:

Flash.py

  1. from flask import Flask, flash, redirect, render_template, request, url_for
  2. app = Flask(name)
  3. app.secret_key = 'random string'
  4. @app.route('/')
  5. def index():
  6. return render_template('index.html')
  7. @app.route('/login', methods = ['GET', 'POST'])
  8. def login():
  9. error = None
  10. if request.method == 'POST':
  11. if request.form['username'] != 'admin' or \
  12. request.form['password'] != 'admin':
  13. error = 'Invalid username or password. Please try again!'
  14. else:
  15. flash('You were successfully logged in')
  16. return redirect(url_for('index'))
  17. return render_template('login.html', error = error)
  18. if name == "main":
  19. app.run(debug = True)

执行上述代码后,您将看到如下所示的界面。

Flask 学习笔记(二) - 图3

当您点击链接,您将被定向到登录页面。

输入用户名和密码。

Flask 学习笔记(二) - 图4

点击登录。将显示一条消息“您已成功登录”。

Flask 学习笔记(二) - 图5

Flask 文件上传

在 Flask 中处理文件上传非常简单。它需要一个 HTML 表单,其 enctype 属性设置为“multipart / form-data”,将文件发布到 URL。URL 处理程序从 request.files[] 对象中提取文件,并将其保存到所需的位置。

每个上传的文件首先会保存在服务器上的临时位置,然后将其实际保存到它的最终位置。目标文件的名称可以是硬编码的,也可以从 request.files[file]对象的filename属性中获取。但是,建议使用 secure_filename() 函数获取它的安全版本。

可以在 Flask 对象的配置设置中定义默认上传文件夹的路径和上传文件的最大大小。

app.config[‘UPLOAD_FOLDER’] 定义上传文件夹的路径 app.config[‘MAX_CONTENT_LENGTH’] 指定要上传的文件的最大大小(以字节为单位)

以下代码具有 '/ upload'URL 规则,该规则在 templates 文件夹中显示'upload.html',以及 '/ upload-file'URL 规则,用于调用 uploader()函数处理上传过程。

'upload.html'有一个文件选择器按钮和一个提交按钮。

  1. <html>
  2. <head>
  3. <title>File Upload</title>
  4. </head>
  5. <body>
  6. <form action="http://localhost:5000/uploader" method="POST" enctype="multipart/form-data">
  7. <input type="file" name="file" accept=".jpg,.png" />
  8. <input type="submit" />
  9. </form>
  10. </body>
  11. </html>

您将看到如下所示的界面。

选择文件后,单击提交。表单的post方法调用'/ upload_file' URL。底层函数 uploader() 执行保存操作。 以下是 Flask 应用程序的 Python 代码。

  1. from flask import Flask, render_template, request
  2. from werkzeug.utils import secure_filename
  3. import os
  4. app = Flask(__name__)
  5. app.config['UPLOAD_FOLDER'] = 'upload/'
  6. @app.route('/upload')
  7. def upload_file():
  8. return render_template('upload.html')
  9. @app.route('/uploader', methods = ['GET', 'POST'])
  10. def uploader():
  11. if request.method == 'POST':
  12. f = request.files['file']
  13. f.save(os.path.join(app.config['UPLOAD_FOLDER'],secure_filename(f.filename)))
  14. return 'file uploaded successfully'
  15. if __name__ == '__main__':
  16. app.run()

注意:app.config[‘UPLOAD_FOLDER’] = ‘upload/‘upload 前面不能加“/”。 上传成功会显示以下画面:

上次文件被放到根目录的 upload 文件夹下: