Flask + MySQL网站开发 # Flask基础知识 Flask教程: https://www.w3cschool.cn/flask/flask_overview.html ## Flask安装 ```python pip install Flask ``` ![image-20221120232533820](C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20221120232533820.png) ## Flask 一个最小的应用 打开Pycharm软件, 新建一个Python项目, 命名为FlaskDemo,选择Ptyhon环境为Python 3.9. image-20221126042334677 在main.py代码文件中编写如下代码: ```python from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run() ``` 运行程序, 能够看到运行成功, 提示Flask程序已经运行在http://127.0.0.1: 5000端口, 结果如下: image-20221126042623049 直接点击上图中的http://127.0.0.1: 5000链接, 或者在浏览器的地址栏中输入该地址, 即可访问网站,看到Hello World页面. image-20221126042933223 程序解释: (1) "from flask import Flask" 导入了 Flask 类。这个类的实例将会是一个WSGI 应用程序。 (2) "app = Flask(__ name __ )" 创建一个该类的实例,第一个参数是应用模块或者包的名称。 Flask构造函数使用**当前模块(__name __)**的名称作为参数。如果你使用单一的模块(如本例),你应该使用 __ name __ ,因为模块 的名称将会因其作为单独应用启动还是作为模块导入而有不同( 也即是 '__main__' 或实际的导入名)。这是必须的,这样 Flask 才知道到哪去找模板、静态文件等等。 (3) 使用 route() 装饰器告诉 Flask 什么样 的URL 能触发我们的函数。这个函数的名字也在生成 URL 时被特定的函数采用,这个函数返回想要显示在用户浏览器中的信息。 Flask类的**route()**函数是一个装饰器,它告诉应用程序哪个URL应该调用相关的函数。 ``` app.route(rule, options) ``` - **rule** 参数表示与该函数的URL绑定。 - **options** 是要转发给基础Rule对象的参数列表。 在上面的示例中,'/ ' URL与**hello_world()**函数绑定。 因此,当在浏览器中打开web服务器的主页时,将呈现该函数的输出。 (4) Flask类的**run()**方法在本地开发服务器上运行应用程序, 让应用运行在本地服务器上。其中 if __name__ == '__main__': 确保服务器只会在该脚本被 Python 解释器直接执行的时候才会运行,而不是作为模块导入的时候。 ``` 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服务器。 | 欲关闭服务器,按 Ctrl+C。 **(5) 外部可访问的服务器** 如果你运行了这个服务器,你会发现它只能从你自己的计算机上访问,网络 中其它任何的地方都不能访问。在调试模式下,用户可以在你的计算机上执 行任意 Python 代码。因此,这个行为是默认的。 如果你禁用了 debug 或信任你所在网络的用户,你可以简单修改调用 run() 的方法使你的服务器公开可用,如下: ```python app.run(host='0.0.0.0') ``` 这会让操作系统监听所有公网 IP。 ## Flask 调试模式 虽然 run() 方法适用于启动本地的开发服务器,但是 你每次修改代码后都要手动重启它。这样并不够优雅,而且 Flask 可以做到更 好。如果你启用了调试支持,服务器会在代码修改后自动重新载入,并在发生 错误时提供一个相当有用的调试器。 有两种途径来启用调试模式。一种是直接在应用对象上设置: ```python app.debug = True app.run() ``` 另一种是作为 run 方法的一个参数传入: ```python app.run(debug=True) ``` 两种方法的效果完全相同。 ## Flask 路由(页面路由) 现代 Web 应用的 URL 十分优雅,易于人们辨识记忆,这一点对于那些面向使 用低速网络连接移动设备访问的应用特别有用。如果可以不访问索引页,而是 直接访问想要的那个页面,他们多半会笑逐颜开而再度光顾。 如上所见, route() 装饰器把一个函数绑定到对应的 URL 上。 例如: 在main.py文件中编写以下函数, 实现flask的路由(页面跳转) ```python @app.route('/') def hello_world(): return 'Hello World!' @app.route('/page2') def gopage2(): return '你好' ``` 在这里,URL **'/page2'** 规则绑定到gopage2()**函数。 因此,如果用户访问**http://localhost:5000/page2 , gopage2()函数的输出将在浏览器中呈现。 application对象的**add_url_rule()**函数也可用于将URL与函数绑定,如上例所示,使用**route()**。 装饰器的目的也由以下表示: ```python def gopage2(): return '你好' app.add_url_rule('/', 'page2', gopage2) ``` image-20221126050322597 重新运行程序, 访问http://127.0.0.1:500/page2, 即可看到page2页面以及内容. image-20221126044147717 如何通过路由链接到一个已存在的页面? 使用如下代码: 具体见"Falsk HTTP方法"小节的内容. ``` return render_template("xxx.html") ``` ## Flask 变量规则(参数传递) 通过向规则参数添加变量部分,可以动态构建URL。 此变量部分标记为**** 。 它作为关键字参数传递给与规则相关联的函数。 在以下示例中,**route()**装饰器的规则参数包含附加到URL **'/hello'** 的**。** 因此,如果在浏览器中输入**http://localhost:5000/hello/sysu**作为**URL**,则**'sysu'**将作为参数提供给 **hello_name()**函数。 ```python from flask import Flask app = Flask(__name__) @app.route('/hello/') def hello_name(name): return '你好, %s!' % name if __name__ == '__main__': app.run(debug = True) ``` image-20221126050919462 接下来,打开浏览器并输入URL **http:// localhost:5000/hello/sysu。** 以下输出将显示在浏览器中: image-20221126050808386 除了默认字符串变量部分之外,还可以使用以下转换器构建规则: | 序号 | 转换器 | 描述 | | :--: | :-------: | :----------------------: | | 1 | **int** | 接受整数 | | 2 | **float** | 对于浮点值 | | 3 | **path ** | 接受用作目录分隔符的斜杠 | 在下面的代码中,使用了所有这些构造函数: ```python from flask import Flask app = Flask(__name__) @app.route('/blog/') def show_blog(postID): return 'Blog Number %d' % postID @app.route('/rev/') def revision(revNo): return 'Revision Number %f' % revNo if __name__ == '__main__': app.run() ``` 从Python Shell运行上面的代码。访问浏览器中的URL **http://localhost:5000/blog/32。 给定的数字用作**show_blog()**函数的参数。浏览器显示以下输出: image-20221126051048005 在浏览器中输入此URL - **http://localhost:5000/rev/3.5** **revision()**函数将浮点数作为参数。以下结果显示在浏览器窗口中: image-20221126051122351 Flask的URL规则基于**Werkzeug**的路由模块。 这确保形成的URL是唯一的,并且基于Apache规定的先例。 考虑以下脚本中定义的规则: ```python from flask import Flask app = Flask(__name__) @app.route('/flask') def hello_flask(): return 'Hello Flask' @app.route('/python/') def hello_python(): return 'Hello Python' if __name__ == '__main__': app.run() ``` 这两个规则看起来类似,但在第二个规则中,使用斜杠**(/)**。因此,它成为一个规范的URL。 因此,使用 **/python** 或 **/python/**返回相同的输出。 image-20221126051347803 image-20221126051335208 但是,如果是第一个规则,**/flask/ URL**会产生“404 Not Found”页面。 image-20221126051244677 image-20221126051301045 ## Flask URL构建(多页面跳转) **url_for()**函数对于动态构建特定函数的URL非常有用。 **url_for()**函数接受函数的名称作为第一个参数,以及一个或多个关键字参数,每个参数对应于URL的变量部分。 以下脚本演示了如何使用**url_for()**函数: ```python from flask import Flask, redirect, url_for app = Flask(__name__) @app.route('/admin') def hello_admin(): return 'Hello Admin' @app.route('/guest/') def hello_guest(guest): return 'Hello %s as Guest' % guest @app.route('/user/') def hello_user(name): if name =='admin': return redirect(url_for('hello_admin')) else: return redirect(url_for('hello_guest', guest = name)) if __name__ == '__main__': app.run() ``` image-20221126052148990 说明: 以上功能需要用到Flask库中的redirect和 url_for函数, 因此需要先import进来. 上述脚本有一个函数**hello_user****(name)**,它接受来自URL的参数的值。 **hello_user****()**函数检查接收的参数是否与**'admin'**匹配。 如果匹配,则使用**url_for()**将应用程序重定向到**hello_admin()**函数,否则重定向到将接收的参数作为guest参数传递给它的**hello_guest()**函数。 保存上面的代码并从Python shell运行。 打开浏览器并输入URL - **[http://localhost:5000/user/admin](http://localhost:5000/hello/admin)** 浏览器中的应用程序响应是: image-20221126052235405 在浏览器中输入以下URL - **[http://localhost:5000/user/cc](http://localhost:5000/hello/cc)** 应用程序响应现在更改为: image-20221126052256861 如果不传参数, 则会提示找不到页面. 因为函数中没有编写此类情况的处理. image-20221126052224596 **Flask 重定向** Flask类有一个**redirect()**函数。调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。 **redirect()**函数的原型如下: ``` Flask.redirect(location, statuscode, response) ``` 在上述函数中: - **location**参数是应该重定向响应的URL。 - **statuscode**发送到浏览器标头,默认为302。 - **response**参数用于实例化响应。 ## 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。 将以下脚本另存为login.html ```html

Enter Name:

``` 新建一个python文件,命名为demo2.py, 输入以下代码: ```python from flask import Flask, redirect, url_for, request, render_template app = Flask(__name__) @app.route('/') def index(): return render_template("login.html") @app.route('/success/') def success(name): return 'welcome %s' % name @app.route('/login',methods = ['POST', 'GET']) def login(): if request.method == 'POST': print(1) user = request.form['nm'] return redirect(url_for('success',name = user)) else: print(2) user = request.args.get('nm') return redirect(url_for('success',name = user)) if __name__ == '__main__': app.run(port=5001) ``` 注意, 由于端口号5000已经被刚才的main.py程序使用了, 因此, demo2.py程序可以使用一个新的端口号,例如:5001. 开发服务器开始运行后,在浏览器中打开**login.html**,在文本字段中输入name,然后单击**提交**。 image-20221126053747087image-20221126053935292 注意,此时需要打开html文件所在的文件夹, 直接双击该login.html文件才能访问页面. 如果直接在地址栏中输入:127.0.0.1:5001,则会提出Internal Server Error错误, 错误原因是jinja2.exception.TemplateNotFound: login.html, 即, 没有将login.html没有设为模板页. 如果直接在地址栏中输入: 127.0.0.1:5001/login.html, 则会提示找不到该页面. image-20221126053802163 image-20221126054657118image-20221126053717276 表单数据将POST到表单标签的action子句中的URL。 **http://localhost/login**映射到**login()**函数。由于服务器通过**POST**方法接收数据,因此通过以下步骤获得从表单数据获得的“nm”参数的值: ``` user = request.form['nm'] ``` 它作为变量部分传递给**'/success'** URL。浏览器在窗口中显示**welcome** 消息。 image-20221126054429802 在**login.html**中将方法参数更改为**'GET'**,然后在浏览器中再次打开它。服务器上接收的数据是通过**GET**方法获得的。通过以下的步骤获得'nm'参数的值: ``` User = request.args.get('nm') ``` 这里,**args**是包含表单参数对及其对应值对的列表的字典对象。与'nm'参数对应的值将像之前一样传递到'/ success' URL。 image-20221126054529401 # Flask进阶 ## Flask 模板(静态模板页面+动态数据渲染) 在前面的实例中,视图函数的主要作用是生成请求的响应,这是最简单的请求。 **视图函数有两个作用:** - 处理业务逻辑 - 返回响应内容 在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本. - 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取 - 使用真实值替换变量,再返回最终得到的字符串,这个过程称为'渲染' - Flask 是使用 Jinja2 这个模板引擎来渲染模板 **使用模板的好处** - 视图函数只负责业务逻辑和数据处理(业务逻辑方面) - 而模板则取到视图函数的数据结果进行展示(视图展示方面) - 代码结构清晰,耦合度低 **(1) 模板基本使用** 在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件 html 文件 hello.html ```html Title 我的模板html内容 ``` image-20221126055724039 创建一个demo3.py文件,在route视图函数中, 将该模板内容进行渲染返回 ```python from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('hello.html') ``` 运行程序, 在浏览器中访问http://127.0.0.1:5000,即可跳转到hello.html页面 image-20221126060540371 **(2)模板变量** 代码中传入字符串,列表,字典到模板中 ```python from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): # 往模板中传入的数据 my_str = 'Hello Word' my_int = 10 my_array = [3, 4, 2, 1, 7, 9] my_dict = { 'name': 'xiaoming', 'age': 18 } return render_template('hello.html', my_str=my_str, my_int=my_int, my_array=my_array, my_dict=my_dict ) ``` 在HTML模板中,编写相应的变量。 ```html Title 我的模板html内容
{{ my_str }}
{{ my_int }}
{{ my_array }}
{{ my_dict }} ``` 运行效果 image-20221126060834425 **(3)示例代码2 :** HTML模板页面脚本,继续编写如下变量,主要是体验list数据元素和字典数据元素的读取。 ```html Title 我的模板html内容
{{ my_str }}
{{ my_int }}
{{ my_array }}
{{ my_dict }}

模板的list数据获取


{{ my_array[0] }}
{{ my_array.1 }}

字典数据获取


{{ my_dict['name'] }}
{{ my_dict.age }}

算术运算


{{ my_array.0 + 10 }}
{{ my_array[0] + my_array.1 }} ``` 不需要修改demo3.py文件中的代码,直接重新运行程序,访问页面,运行结果如下。 image-20221126061337707 ## Flask 静态文件(调用Javascript) Web应用程序通常需要静态文件,例如**javascript**文件或支持网页显示的**CSS**文件。 通常,配置Web服务器并为您提供这些服务,但在开发过程中,这些文件是从您的包或模块旁边的*static*文件夹中提供,它将在应用程序的**/static**中提供。 特殊端点'static'用于生成静态文件的URL。 在下面的示例中,在**index.html**中的HTML按钮的**OnClick**事件上调用**hello.js**中定义的**javascript**函数,该函数在Flask应用程序的**“/”**URL上呈现。 首先,创建一个demo4.py文件,编写如下代码。 ```python from flask import Flask, render_template app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") if __name__ == '__main__': app.run(debug = True) ``` 接着,在templates 文件夹中创建一个index.html文件,编写如下HTML脚本: ```html ``` 在index.html中的HTML按钮的**OnClick**事件上调用**hello.js**中定义的**javascript**函数。 第三,创建一个static文件夹,在static文件夹中创建一个**hello.js**文件,编写**sayHello()**函数。 ```javascript function sayHello() { alert("Hello World") } ``` 重新运行程序,运行效果如下: image-20221126061956548 点击“Say Hello”按钮,调用JavaScript函数,运行JS脚本功能。 image-20221126062101498 ## Flask 将表单数据发送到模板 我们已经看到,可以在 URL 规则中指定 http 方法。触发函数接收的 **Form** 数据可以以字典对象的形式收集它并将其转发到模板以在相应的网页上呈现它。 **(1)Flask Request对象** 来自客户端网页的数据作为全局请求对象发送到服务器。为了处理请求数据,应该从Flask模块导入。 Request对象的重要属性如下所列: - **Form** - 它是一个**字典对象**,包含表单参数及其值的键和值对。 - **args** - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。 - **Cookies** - 保存Cookie名称和值的字典对象。 - **files** - 与上传文件有关的数据。 - **method** - 当前请求方法。 **(2)示例演示** 在以下示例中,**'/' URL** 会呈现具有表单的网页(student.html)。 填入的数据会发布到触发 **result()** 函数的 **'/result' URL**。 **result()** 函数收集字典对象中的 **request.form** 中存在的表单数据,并将其发送给 **result.html**。 该模板动态呈现**表单**数据的 HTML 表格。 下面给出的是应用程序的 Python 代码: 创建一个demo5.py文件,编写如下代码: ```python from flask import Flask, render_template, request app = Flask(__name__) @app.route('/') def student(): return render_template('student.html') @app.route('/result',methods = ['POST', 'GET']) def result(): if request.method == 'POST': result = request.form return render_template("result.html",result = result) if __name__ == '__main__': app.run() ``` image-20221126064904320 接着,在templates文件夹下创建一个student.html页面文件,编写如下Form表单脚本。 ```HTML Student Register

Name

Physics

Chemistry

Maths

``` image-20221126064934672 然后,在templates文件夹下创建一个result.html页面文件,编写如下模板代码: ```html Student Information {% for key, value in result.items() %} {% endfor %}
{{ key }} {{ value }}
``` image-20221126065006719 运行程序,在浏览器中输入 URL **http://localhost:5000/**。 image-20221126064509554 image-20221126064603853 当点击**提交**按钮时,表单数据以 HTML 表格的形式呈现在 **result.html** 上。可以看到结果被遍历显示在页面的表格中。 image-20221126064733344 ## Flask Session会话(登录判断) 会话是客户端登录到服务器并注销服务器的时间间隔,需要在该会话中保存的数据会存储在服务器上的临时目录中。 为每个客户端的会话分配**会话ID**,**Session(会话)**数据存储在服务器上。服务器以加密方式对其进行签名。对于此加密,Flask应用程序需要一个定义的**SECRET_KEY**。 Session对象也是一个字典对象,包含会话变量和关联值的键值对。 例如,要设置一个**'username'**会话变量,请使用以下语句: ``` Session['username'] = 'admin' ``` 要释放会话变量,请使用**pop()**方法。 ``` session.pop('username', None) ``` 创建一个demo6_session.py文件,编写以下代码,作为Flask中的会话工作的简单演示。 首先,创建一个Falsk对象,定义一个密钥,密钥内容自己写,可以是任意随机的字符串。 编写route('/')函数,URL **'/'**只是提示用户登录,因为此时还没有设置会话变量**'username'**的值。 ```python from flask import Flask, session, redirect, url_for, request app = Flask(__name__) app.secret_key = 'fkdjsafjdkfdlkjfadskjfadskljdsfklj' @app.route('/') def index(): if 'username' in session: username = session['username'] return '登录用户名是:' + username + '
' + \ "点击这里注销" return "您暂未登录,
" + \ "点击这里登录" ``` 当用户浏览到“/login”login()视图函数时,因为它是通过GET方法调用的,所以将打开一个登录表单。 表单发送回**'/login'**,现在会话变量已设置。应用程序重定向到**'/'**。此时会话变量**'username'**被找到。 ```python @app.route('/login', methods = ['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return '''

''' ``` 应用程序还包含一个**logout()**视图函数,它会弹出**'username'**会话变量。因此,**'/'** URL再次显示开始页面。 ```python @app.route('/logout') def logout(): # remove the username from the session if it is there session.pop('username', None) return redirect(url_for('index')) ``` 完整代码如下所示: ```python from flask import Flask, session, redirect, url_for, request app = Flask(__name__) app.secret_key = 'fkdjsafjdkfdlkjfadskjfadskljdsfklj' @app.route('/') def index(): if 'username' in session: username = session['username'] return '登录用户名是:' + username + '
' + \ "点击这里注销" return "您暂未登录,
" + \ "点击这里登录" @app.route('/login', methods = ['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return '''

''' @app.route('/logout') def logout(): # remove the username from the session if it is there session.pop('username', None) return redirect(url_for('index')) if __name__ == '__main__': app.run(port=5001) ``` image-20221126070625456 运行程序,效果如下。 image-20221126070112071 点击**“点击此处登录”**链接。链接将被定向到另一个屏幕。键入“admin”。 image-20221126070132041image-20221126070143531 屏幕会显示消息“ **登录用户名是:admin** ”。 点击”**点击这里注销**“链接,则会删除Session变量,并跳转到login页面。 image-20221126070158809image-20221126070209909 ## Flask 消息闪现 Flask 提供了一个非常简单的方法来使用闪现系统向用户反馈信息。闪现系统使得在一个请求结束的时候记录一个信息,并且在下次(且仅在下一次中)请求时访问它,这通常与布局模板结合使用以公开信息。 在 Flask Web 应用程序中生成这样的信息性消息很容易。Flask 框架的闪现系统可以在一个视图中创建消息,并在名为 **next** 的视图函数中呈现它。 Flask 模块包含 **flash()** 方法。它将消息传递给下一个请求,该请求通常是一个模板。 ```python flash(message, category) ``` 其中, - **message** 参数是要闪现的实际消息。 - **category** 参数是可选的。它可以是“error”,“info”或“warning”。 为了从会话中删除消息,模板调用 **get_flashed_messages()**。 ```python get_flashed_messages(with_categories, category_filter) ``` 两个参数都是可选的。如果接收到的消息具有类别,则第一个参数是元组。第二个参数仅用于显示特定消息。 以下闪现在模板中接收消息。 ```html {% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %} {{ message }} {% endfor %} {% endif %} {% endwith %} ``` **示例** 创建一个demo7_flash.py文件,编写如下代码。演示Flask中的闪现机制。 **'/'** URL 显示登录页面的链接,没有消息闪现。 ```python @app.route('/') def index(): return render_template('index.html') ``` 接着编写/login函数,该链接会将用户引导到**'/login'** URL,该 URL 显示登录表单。 提交时,**login()** 视图函数验证用户名和密码,并相应闪现 **'success'** 消息或创建 **'error'** 变量。 ```python @app.route('/login', methods = ['GET', 'POST']) def login(): error = None if request.method == 'POST': if request.form['username'] != 'admin' or request.form['password'] != 'admin': error = 'Invalid username or password. Please try again!' else: flash('You were successfully logged in') return redirect(url_for('index')) return render_template('login.html', error = error) ``` 如果出现**错误**,则会重新显示登录模板,并显示错误消息。 下面给出了 Flask 消息闪现示例的完整代码: **(1)demo7_flash.py** ```python from flask import Flask, flash, redirect, render_template, request, url_for app = Flask(__name__) app.secret_key = 'random string' @app.route('/') def index(): return render_template('index7.html') @app.route('/login', methods = ['GET', 'POST']) def login(): error = None if request.method == 'POST': if request.form['username'] != 'admin' or request.form['password'] != 'admin': error = 'Invalid username or password. Please try again!' else: flash('You were successfully logged in') return redirect(url_for('index')) return render_template('login7.html', error = error) if __name__ == '__main__': app.run(port=5002) ``` image-20221126074431124 **(2)login7.html** 接着编写login.html文件,在页面中编写一个Form表单,编写username和password的表单控件,提交路径为“/login”,这会将表单数据传入demo7_flask.py文件中的/login函数。编写error模板代码,将显示flask的消息。 ```html Login
Username
Password
{% if error %}

Error: {{ error }}

{% endif %} ``` image-20221126074522343 **(3) Index7.html** 另一方面,如果登录成功,则会在索引模板上刷新成功消息。 ```html Index {% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %}

{{ message }}

{% endfor %} {% endif %} {% endwith %}

Welcome!

login ``` image-20221126074555323 运行程序,在浏览器中访问http://127.0.0.1:5002,运行界面如下: image-20221126074129900 点击“login”链接,您将被定向到登录页面。输入用户名和密码。 image-20221126074141814image-20221126074151415 当输入的用户名不为"admin"、密码也不为"admin"时(admin是自己在程序中写的,可以更换),在当前页面直接示意用户名或者密码错误。 image-20221126074238983 当用户名或者密码输入成"admin"时,再点击**登录**。将跳转到index7.html页面中,并显示一条消息“您已成功登录”。 image-20221126074314927 ## 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文件** 在templates文件夹中创建一个**upload.html**网页文件, 在里面编写一个表单, 包含一个文件选择器按钮和一个提交按钮。 ```html File Upload
``` image-20221126163655697 创建一个demo8_uploadfile.py文件, 编写如下代码: 表单的` post `方法调用` '/upload_file'` URL。 底层函数 `uploader()` 执行保存操作。 ```python from flask import Flask, render_template, request from werkzeug.utils import secure_filename import os app = Flask(__name__) app.config['UPLOAD_FOLDER'] = 'upload/' @app.route('/upload') def upload_file(): return render_template('upload.html') @app.route('/uploader',methods=['GET','POST']) def uploader(): if request.method == 'POST': f = request.files['file'] print(request.files) f.save(os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(f.filename))) return 'file uploaded successfully' else: return render_template('upload.html') if __name__ == '__main__': app.run(port=5005) ``` 接着,在项目根目录下创建一个upload文件夹, 用于存放要上传的文件. 注意:app.config['UPLOAD_FOLDER'] = 'upload/', upload 前面不能加“/”。 运行程序, 直接在浏览器地址栏中输入: http://127.0.0.1/upload, 效果如下所示: image-20221126163509367image-20221126164827930 选择文件后,单击提交。上传成功会显示以下画面: image-20221126164541444 最后,到upload文件夹中查看, 上传的文件被放到根目录的 upload 文件夹下: image-20221126164647528 ## Flask WTF Web应用程序的一个重要方面是为用户提供用户界面。HTML提供了一个**
**标签,用于设计界面。 可以适当地使用**Form(表单)** 元素,例如文本输入,单选按钮,选择等。 用户输入的数据以Http请求消息的形式通过GET或POST方法提交给服务器端脚本。 - 服务器端脚本必须从http请求数据重新创建表单元素。因此,实际上,表单元素必须定义两次 - 一次在HTML中,另一次在服务器端脚本中。 - 使用HTML表单的另一个缺点是很难(如果不是不可能的话)动态呈现表单元素。HTML本身无法验证用户的输入。 这就是**WTForms**的作用,一个灵活的表单,渲染和验证库,能够方便使用。 Flask-WTF扩展为这个**WTForms**库提供了一个简单的接口。 使用**Flask-WTF**,我们可以在Python脚本中定义表单字段,并使用HTML模板进行渲染。还可以将验证应用于**WTF**字段。 让我们看看这种动态生成的HTML是如何工作的。 首先,需要安装Flask-WTF扩展。 ``` pip install flask-WTF ``` image-20221126165233287 已安装的软件包包含一个**Form**类,该类必须用作用户定义表单的父级。 **WTforms**包中包含各种表单字段的定义。下面列出了一些**标准表单字段**。 | 序号 | 标准表单字段与描述 | | :--- | :---------------------------------------------------------- | | 1 | **TextField**表示 HTML表单元素 | | 2 | **BooleanField**表示 HTML表单元素 | | 3 | **DecimalField**用于显示带小数的数字的文本字段 | | 4 | **IntegerField**用于显示整数的文本字段 | | 5 | **RadioField**表示 HTML表单元素 | | 6 | **SelectField**表示选择表单元素 | | 7 | **TextAreaField**表示