目录
- 一、环境配置安装
- 安装 Virtualenv 虚拟环境
- Virtualenv 虚拟环境内安装 Flask 框架
- Tips:
- 二、Flask 框架的初级学习
- Flask 的 app 补充说明:
- 运行 Flask 的最小应用(app)
- (后期) 解决 Warning 报错,开启 WSGI 服务
- 理解调试模式 app.run
- 理解 Flask 框架的路由
- 题外:Flask 框架 和 Django 框架的路由对比理解
- 理解 Flask 路由URL尾部变量传参规则
- 唯一 URL / 重定向行为
- 什么是 Werkzeug :
- 唯一 URL 及重定向规则案例
- 唯一 URL 和 重定向 个人理解
- Flask 框架自定义生成 URL 的 url_for()
- 生成 URL 个人理解:
- Flask 的 HTTP 请求方法 route('/',methods=[ ])
- Flask 的\static\静态文件生成url_for('static', filename='test.css')
- Flask 的静态文件访问个人理解 :
- 解析客户端 Request 对象的参数
- 处理表单Form的简单实例
- 对 Flask Cookies 的设置与理解
- 在Flask中对Cookie的处理步骤
- set_cookie参数详解:
测试环境:
操作系统: Window 10
工具:Pycharm
Python: 3.7
一、环境配置安装
安装 Virtualenv 虚拟环境
使用 python 的框架,一般最好是弄一个虚拟环境,在虚拟环境内使用框架,这样比较方便后面的项目封装打包,而且可以对该项目运行环境与其他的项目的运行环境进行一个隔离,不会导致版本的冲突。
具体的看创建虚拟环境实操链接
Virtualenv 虚拟环境内安装 Flask 框架
cd 虚拟环境下的 Scripts 目录下
这样才可以调用虚拟环境内的 pip 指令下载 Flask 框架,而不是给本地下载 Flask 框架
pip install flask

Flask 或 flask 大小写都可以
过程演练:


Tips:
最好在虚拟环境目录的Scripts目录下,安装Flask框架模块。
Flask 项目最好是手动创建虚拟环境,然后在Pycharm开发工具内创建Flask 项目,具体如下所示:

上面红框内虚拟环境名\config 是在虚拟环境内新建的项目文件夹 config,Flask项目的脚本文件都放在这里,下面的红框内的解释器路径是之前创建好的虚拟环境的python解释器的路径,注意这里指定好了(FlaskProject),而不是(FlaskProject)(1) 或 (FlaskProject)(2)、(FlaskProject)(3)…(FlaskProject)(n),这里就是 Pycharm 神奇的地方了,重复创建一个虚拟环境下的python解释器,让人感觉很难受,所以才强调要用手动创建虚拟环境。
创建结果:

当然为什么坚持要使用虚拟环境,这是为了运行环境隔离,后期封装就简单多了。
二、Flask 框架的初级学习
Flask 的 app 补充说明:
对于 Flask 框架来说,一个 python 文件就是一个 app
运行 Flask 的最小应用(app)
最小应用代码演示:
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
保存为一个 app.py 脚本文件,当然需要注意的是以后给文件起名字,请确保你不会将它的文件名弄成 flask.py,这样会和 Flask 框架文件名冲突的。
运行 python 命令:(前面我弄了一个 FlaskProject 的 virtualenv 虚拟环境,后面就一直用这个虚拟环境,学习 Flask 框架)
这里分为两种运行方式:一种是Pycharm,另外一种是Windows 终端,不过这里就混合使用两种方式来测试,可以对比一下。
Pycharm运行
直接点击蓝色的URL,就可以自动弹出网页
Windows终端运行

终端运行成功,后在浏览器输入 127.0.0.1:5000 就可以看到结果 Hello World!
不过,看到红色的没有,警告 Warning,其实也没啥,只是 WSGI 没开启,这个模式用于开发环境调试,部署线上需要使用WSGI替代,所以这里就需要启动 WSGI 服务。
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
警告:这是一个开发服务器。不要在生产部署中使用它。使用一个生产WSGI服务器代替。
解决方法:
参考链接:
https://blog.csdn.net/panruola/article/details/106012487
https://blog.csdn.net/GodDavide/article/details/103712131
https://www.cnblogs.com/mlp1234/p/13743254.html
http://www.wsmee.com/post/79
其实初学者,不建议一开始就按照我下面的做法,下面环节只是后期要做的,只是大致给个具体的做法而已。一般还是先用上面环节内的 app.run,正式环节才采用下面的开启 wsgi 服务器的做法。
(后期) 解决 Warning 报错,开启 WSGI 服务
安装 gevent 模块,导入 pywsgi,代码如下所示:
# hello.py
from flask import Flask
from gevent import pywsgi
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
server = pywsgi.WSGIServer(('0.0.0.0', 5000), app)
server.serve_forever()
0.0.0.0 —— 这会让操作系统监听所有公网 IP。
结果如下:
这里就不会弹出类似这种的输出显示了

而是这种,好像没运行一样的空白终端。

不过得在终端ipconfig 一下,找到自己 ip 地址,如果有多个 ip 地址,也没问题,反正只要是自己电脑所属的 ip 地址就行,就可以访问本机电脑服务器,然后随便输入自己电脑的 ip 地址 和 端口号,就可以了。这里可以弄一个测试用的静态 ip 地址,进行测试。

终端会显示有如下的访问记录

理解调试模式 app.run
虽然
run()方法适用于启动本地的开发服务器,但是 你每次修改代码后都要手动重启它。这样并不够优雅,而且Flask可以做到更 好。如果你启用了调试支持,服务器会在代码修改后自动重新载入,并在发生 错误时提供一个相当有用的调试器。
有两种途径来启用调试模式。一种是直接在应用对象上设置:
# hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.debug = True
app.run()
另一种是作为 run 方法的一个参数传入:
# hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True)
两种方法的效果完全相同。
debug - 是否开启调试模式并捕获异常
注意
尽管交互式调试器在允许fork的环境中无法正常使用(即在生产服务器上正常使用几乎是不可能的),但它依然允许执行任意代码。这使它成为一 个巨大的安全隐患,因此它 绝对不能用于生产环境 。
参考链接:
https://www.w3cschool.cn/flask_1/flask_1-74fv3ixu.html
app.run 个人理解:
app.run提供一个调试模式供开发者去自行开发项目,这个run方法,一般是用于开发环节使用的,而不是生产上线环节,而且由于有安全隐患,就更不能用于生产环境,此外,可以开启其调试模式,方便项目开发调试。
理解 Flask 框架的路由
URL (Uniform Resource Locator,统一资源定位器)能够用人所熟悉易于记忆的方式,来指向某个网站网页或文件,而不是用 ip 地址,这样的数字化思维去记忆,这是其很方便且极其重要的特点,我是这样理解的。
Flask 框架对于 URL 是一种绑定的思路,具体实现方法是利用一个 route() 的装饰器来绑定特定的 URL 与 指定的函数 / 方法,实现的代码如下:
# hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
@符号后加app.route()等同于调用装饰器,来装饰下面某个def方法, 括号内指定某个URL字符串 ,下一行则是指定某个URL特定函数 / 方法
题外:Flask 框架 和 Django 框架的路由对比理解
突然想来对比下两个框架的路由,没学过 Django 框架的,可以翻过了。
Django框架的路由实现思路是 主路由表、子路由表及路由URL绑定;
Flask框架的路由实现思路是 路由URL绑定;
这么一想,其实都是有共同点的,那就是路由 URL 绑定,都是通过路由 URL 绑定一个实现 URL 回传 html 的方法,只不过 Django 框架有着主路由表和子路由表,Flask 框架没有,仅仅是 路由 URL 绑定,有点像是精简了路由的 Django 框架。
理解 Flask 路由URL尾部变量传参规则
Flask 框架的 URL 内是可以传递变量的,该变量包括了传递用户名、表单的 id 号等等,而且这些变量是可以指定数据类型的,如整型、浮点型以及路径字符串。
要给
URL添加变量部分,你可以把这些特殊的字段标记为<variable_name>,
这个部分将会作为命名参数传递到你的函数。规则可以用\<converter:variable_name>指定一个可选的数据类型转换器。这里有一些不错的例子:
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
转换器有下面几种:
| 类型 | 作用 |
|---|---|
int | 接受整数 |
float | 同 int ,但是接受浮点数 |
path | 和默认的相似,但也接受斜线 |
唯一 URL / 重定向行为
Flask的URL规则基于Werkzeug的路由模块。这个模块背后的思想是基 于Apache以及更早的HTTP服务器主张的先例,保证优雅且唯一的URL。
什么是 Werkzeug :
首先,先向大家介绍一下什么是
Werkzeug,Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下,Werkzeug不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web框架的底层库,因为它封装好了很多 Web 框架的东西,例如Request,Response等等。
其中Flask框架就是以Werkzeug为基础开发的
唯一 URL 及重定向规则案例
以这两个 URL 规则为例:
# hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/test1/')
def urltest1():
return '有斜线'
@app.route('/test2')
def urltest2():
return '没有斜线'
if __name__ == '__main__':
app.run(debug = True)
测试 1:
输入URL:127.0.0.1:5000/test1/

测试 2:
输入 URL:127.0.0.1:5000/test1

测试 3:
输入 URL:127.0.0.1:5000/test2

测试 4:
输入 URL:127.0.0.1:5000/test2/

参考引用:
第一种情况中,指向 projects 的规范
URL尾端有一个斜线。这种感觉 很像在文件系统中的文件夹。访问一个结尾不带斜线的URL会被 Flask 重定向到带斜线的规范URL去。
然而,第二种情况的URL结尾不带斜线,类似 UNIX-like 系统下的文件的 路径名。访问结尾带斜线的URL会产生一个404 “Not Found”错误。 这个行为使得在遗忘尾斜线时,允许关联的URL接任工作,与Apache和其它的服务器的行为并无二异。此外,也保证了URL的唯一,有助于 避免搜索引擎索引同一个页面两次。
唯一 URL 和 重定向 个人理解
Flask 框架的路由 URL 绑定方法,一开始的路由 URL 绑定是否添加斜杠的区别是很大的,加斜杠了访问的是文件夹,不加斜杠的访问的是文件 —— 文件夹可以攘括了所有的文件,文件单单指的是某种类型的一个文件,文件夹可以补全斜杠,而文件无法补全斜杠。
404 报错,也是因为找不到文件夹,定义为文件,那么自然不会有文件夹。
Flask 框架自定义生成 URL 的 url_for()
用
url_for()来给指定的函数构造URL。它接受函数名作为第一个 参数,也接受对应URL规则的变量部分的命名参数。未知变量部分会添加到URL末尾作为查询参数。
代码例子演示:
# app.py
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/') # 客户端请求的URL
def index():
pass
@app.route('/login') # 客户端请求的URL
def login():
pass
@app.route('/user/<username>') # 客户端请求的URL
def profile(username):
pass
with app.test_request_context(): # 服务端回传的URL
print(url_for('index')) # 服务端回传的URL
print(url_for('login')) # 服务端回传的URL
print(url_for('login', test='/')) # 服务端回传的URL
print(url_for('profile', username='John Doe')) # 服务端回传的URL
运行结果:

URL解析:
login 是无参数方法且作为 url_for() 的第一个参数,第二个参数,指的是URL,而 ? 后的未知变量部分,而且等于号 = 后为字符串形式’ ’ / " "
特别注意:URL是斜杠
/,而Windows的文件路径是反斜杠\
profile 是有参数方法,因为有参数,可以作为关键字参数传参,所以不像 login 那样,有一个 test 这样的 ? 未知变量部分,直接传递参数数值,无需添加 ? 未知变量部分
为什么你要构建
URL而非在模板中硬编码?这里有三个绝妙的理由:
- 反向构建通常比硬编码的描述性更好。更重要的是,它允许你一次性修改
URL, 而不是到处边找边改。URL构建会转义特殊字符和Unicode数据,免去你很多麻烦。- 如果你的应用不位于
URL的根路径(比如,在 /myapplication 下,而不 是/),url_for()会妥善处理这个问题。
生成 URL 个人理解:
url_for() 这里是生成 URL 是一种灵活的方法,url_for() 绑定的是方法,返回值是route() 装饰器的 URL参数加上变量部分,从而生成的 URL 结果。这里要特别注意的一点是,方法,也就是函数,在绑定 URL 路由时,路由的名字,也就是斜杠 / 后的 URL 部分,是否要和方法同名,这一点得灵活一点,可以一样,我认为有时为了安全,需要不一样,如下所示:

Flask 的 HTTP 请求方法 route(‘/’,methods=[ ])
浏览器的发送数据请求方法,是有好几种的不同的方法的,最常见的是 GET 和 POST —— GET 请求的内容是显示在 URL 这里,而 POST 请求请求的内容是放在请求的包内的,比较安全。
Flask 框架的
HTTP(与 Web 应用会话的协议)有许多不同的访问URL方法。默认情况下,路 由只回应GET请求,但是通过route()装饰器传递methods参数可以改变这个行为。
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
如果存在
GET,那么也会替你自动地添加HEAD,无需干预。它会确保 遵照< a rel="nofollow" class="reference external" href="http://www.ietf.org/rfc/rfc2068.txt" rel="external nofollow" target="_blank" >HTTP RFC(描述 HTTP 协议的文档)处理HEAD请求,所以你可以 完全忽略这部分的HTTP规范。同样,自从Flask 0.6起, 也实现了OPTIONS的自动处理。
这里只是大致介绍 HTTP 的常用一些方法,详情请自行搜索相关内容。
HTTP 方法(也经常被叫做“谓词” —— 动词 请求…)告知服务器,客户端想对请求的页面 做 些什么。自从
Flask 0.6起, 也实现了OPTIONS的自动处理。 下面的都是非常常见的方法:
GET
浏览器告知服务器:只获取页面上的信息并发给我。这是最常用的方法。
HEAD
浏览器告诉服务器:欲获取信息,但是只关心 消息头 。应用应像处理
GET请求一样来处理它,但是不分发实际内容。在Flask中你完全无需人工干预,底层的Werkzeug库已经替你打点好了。
POST
浏览器告诉服务器:想在
URL上 发布 新信息。并且服务器必须确保 数据已存储且仅存储一次。这是HTML表单通常发送数据到服务器的方法。
PUT
类似
POST但是服务器可能触发了存储过程多次,多次覆盖掉旧值。你可能会问这有什么用,当然这是有原因的。考虑到传输中连接可能会丢失,在这种情况下浏览器和服务器之间的系统可能安全地第二次接收请求,而不破坏其它东西。因为POST它只触发一次,所以用POST是不可能的。可靠性问题,上传大文件,可以使用PUT。
DELETE
删除给定位置的信息。
OPTIONS
给客户端提供一个敏捷的途径来弄清这个
URL支持哪些HTTP方法。 从Flask 0.6开始,实现了自动处理。
简洁记忆:
也就是说 methods 的参数值是一个 list 列表,列表 list 里面的请求方法,都是一个字符串类型的数据。
有趣的是,在
HTML4和XHTML1中,表单只能以GET和POST方法提交到 服务器。但是JavaScript和未来的HTML标准(如HTML 5)允许你使用其它所有的方法。此 外,HTTP最近变得相当流行,浏览器不再是唯一的HTTP客户端。比如,许多版本控制系统就在使用HTTP。
Flask 的\static\静态文件生成url_for(‘static’, filename=‘test.css’)
动态 web 应用也会需要静态文件,通常是
CSS和JavaScript文件。理想状况下, 你已经配置好 Web服务器来提供静态文件,但是在开发中,Flask也可以做到。 只要在你的包中或是模块的所在目录中创建一个名为static的文件夹,在应用中使用/static即可访问。
给静态文件生成 URL ,使用特殊的 'static' 端点名:
url_for('static', filename='style.css')
这个文件应该存储在文件系统上的 static/style.css 。
Flask 的静态文件访问个人理解 :
Flask 的静态文件默认是在 /static/ 的目录,在这个目录下,比如一些静态、动态图片、还有一些例如javascript文件或支持网页显示的CSS文件等等,都可以放在这里面,而首页这些html模板文件,就都放在 templates 目录下,并且使用方法 render_templates(html文件),Flask框架会在这个目录下查找html模板文件。
代码演示:
# app.py
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>
<head>
<script type = "text/javascript"
src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
</head>
<body>
<input type = "button" onclick = "sayHello()" value = "Say Hello" />
</body>
</html>
\static\hello.js 文件内容:
function sayHello() {
alert("Hello World")
}

运行结果:

解析客户端 Request 对象的参数
来自客户端网页的数据作为全局请求对象发送到服务器。为了处理请求数据,应该从Flask模块导入。
Request对象的重要属性如下所列:
| 参数 | 功能 |
|---|---|
Form | 它是一个字典对象,包含表单参数及其值的键和值对。 |
args | 解析查询字符串的内容,它是问号(?)之后的URL的一部分。 |
Cookies | 保存Cookie名称和值的字典对象。 |
files | 与上传文件有关的数据。 |
method | 当前请求方法 |
处理表单Form的简单实例
python代码文件:
# app.py
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(debug = True)
student.html 表单模板文件:
<form action="http://localhost:5000/result" method="POST">
<p>Name <input type = "text" name = "Name" /></p>
<p>Physics <input type = "text" name = "Physics" /></p>
<p>Chemistry <input type = "text" name = "chemistry" /></p>
<p>Maths <input type ="text" name = "Mathematics" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
表单处理结果回传result.html模板文件
<!doctype html>
<table border = 1>
{% for key, value in result.items() %}
<tr>
<th> {{ key }} </th>
<td> {{ value }}</td>
</tr>
{% endfor %}
</table>
运行结果:


对 Flask Cookies 的设置与理解
Cookie以文本文件的形式存储在客户端的计算机上。其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和网站统计信息。
Request对象包含Cookie的属性。它是所有cookie变量及其对应值的字典对象,客户端已传输。除此之外,cookie还存储其网站的到期时间,路径和域名。
这说明Cookie能够设置登录连接时长和是否启用关闭浏览器等于关闭登录连接。
在Flask中对Cookie的处理步骤
- 设置客户端的cookie:
设置cookie,默认有效期是临时cookie,浏览器关闭就失效
可以通过max_age设置有效期, 单位是秒
set_cookie参数详解:
set_cookie(cookie="",value="",max_age=None,expires=None,path="/",domain=None,secure=False,httponly=False)
cookie=““的名字(删除时也要使用)。
value=””, cookie的值
max_age=None,过期时间(单位为秒)。距离现在多少秒后cookie将过期。
expires=None, 为datetime类型。
path="/", 默认在‘/’表示在当前域名下的所有URL都有效。
domain=None, 设置cookie有效域名
secure=False,False表示在http下使用,True表示在https下使用
httponly=False,True表示只能被浏览器读取,不能被js读取
设置回传给客户端 cookie 的相关配置
resp = make_response("success") # 设置响应体,成功创建了客户端cookie
resp.set_cookie("test", "test", max_age=3600) # 创建 test cookie,时长1小时
# 前面的"test"是cookie的键名,后面的是键值"test"
- 获取客户端的cookie
获取cookie,通过request.cookies的方式, 返回的是一个字典,可以获取字典里的相应的值
cookie_1 = request.cookies.get("test")
可以从客户端请求中获取客户端的cookie信息
3.删除cookie
这里的删除只是让cookie过期,并不是直接删除cookie
删除cookie,通过delete_cookie()的方式, 里面是cookie的名字
resp = make_response("del success") # 设置响应体,成功删除了客户端cookie
resp.delete_cookie("test")
对过期的 cookie 进行删除,否则过期的cookie还是会存在的。
完整代码演示:
from flask import Flask, make_response, request # 注意需导入 make_response
app = Flask(__name__)
@app.route("/set_cookies")
def set_cookie():
resp = make_response("success")
resp.set_cookie("cookiename", "cookievalue",max_age=3600)
return resp
@app.route("/get_cookies")
def get_cookie():
cookie_1 = request.cookies.get("cookiename") # 获取名字为test对应cookie的值
return cookie_1
@app.route("/delete_cookies")
def delete_cookie():
resp = make_response("del success")
resp.delete_cookie("test")
return resp
if __name__ == '__main__':
app.run(debug=True)
运行结果:



测试下cookie还存不存在

查看下删除cookie后,服务器的回传信息,按键盘上的F12

Ctrl+R

注意这里不是双击名称下的cookie,而是单击cookie。




















