flask的使用
前面是Flask的快速使用, 这里完善一下Flask的使用!!
# werkzeug返回值
werkzeug不依赖于flask, 自己就可以完成一个网站.. 那它的返回值咋写呢? 我们可以探究下flask的源码!
通过flask源码反推wsgi返回值!! 看源码的过程 在pycharm里不断跳转 注重其返回值就行!!
★ 这个技巧务必掌握! 看返回值 --〉看调用了谁 --〉自己自定义修改扩展..
ok, 我们来测试下, 是完全没问题的!! 哈哈哈哈 有点意思..
from werkzeug.serving import run_simple
from werkzeug.wrappers import Response # Response的父类是BaseResponse,使用BaseResponse也是可以的!!
def func(environ, start_response):
return Response("Hello World!!")(environ, start_response)
if __name__ == "__main__":
run_simple('localhost', 5001, func)
2
3
4
5
6
7
8
9
10
# 静态文件的处理
先来看看规则
但一般情况下, static_folder和static_url_path我们都使用默认值即可!! 标准写法如下:
# 尽管Flask的static_url_path的默认参数值为None,但实验下来,若不显式指定前缀,则前缀默认为/static
app = Flask(__name__,template_folder='templates',static_folder='static')
<img src="{{ url_for('static',filename='keep1.png')}}" alt=""> # 嵌套了目录的话 xx/xx/keep1.png
-- ★ 当静态文件目录名改变后,img的地址会 [动态] 跟着变!! eg: static_folder='yy' 则对应前缀默认为'/yy'
2
3
4
5
6
# 配置文件相关
Django支持第一种,Flask第一种第二种都支持!!
# 基于全局变量
★ 在本地,一般我们会在settings.py中写公共的配置,在localsettings.py中写本地数据库等私密的配置!!
- 当我们git上传项目到github时
即在执行git add . 之前, 需将localsettings.py加入忽略文件.gitigonre!! config/localsettings.py
- 然后服务器拉取github中的项目进行部署. 我们需要在服务器上自己创建一个localsettings.py,里面写入线上数据库的配置!!
- 新员工从github上拉取项目进行开发,需自己进行数据库的配置在本地进行测试开发,线上数据库它是不知道,动不了的!!
经过上述的过程,保密性很好!!
- 当然,我们可以在settings.py中写上测试数据库的配置!这样更方便大家开发,大家就不用在本地弄数据库了!!
★ 特别注意!!配置文件中的变量名需要大写!!
2
3
4
5
6
7
8
9
10
11
# 基于类的方式
BaseSetting中写公共的配置!
# 路由系统
# 路由加载的源码流程
step1: 将url和函数打包成为 rule 对象
step2: 将rule对象添加到 map 对象中
So,以后我们可以 通过 app.url_map 拿到 map对象, 里面有一大推 路由与视图的对应关系!!
当请求进来,进行路由匹配时,就会去app.url_map中找!!
2
3
4
5
# 路由的两种写法
def index():
return render_template('index.html')
app.add_url_rule('/index', 'index', index)
# - 公司里一般用这种方式
@app.route('/login')
def login():
return render_template('login.html')
2
3
4
5
6
7
8
9
# 动态路由
@app.route('/login')
def login():
return render_template('login.html')
@app.route('/login/<name>')
def login(name):
print(type(name)) # str
return render_template('login.html')
@app.route('/login/<int:name>')
def login(name):
print(type(name)) # int
return render_template('login.html')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
flask默认不支持正则路由, 当然, 你可以自己改下源码来实现.. 因为正则路由基本用不到, 我了解了下, 在此处就不总结该方式了..
# 视图
# FBV
# - 方式一
def index():
return render_template('index.html')
app.add_url_rule('/index', 'index', index)
# - 方式二
@app.route('/login')
def login():
return render_template('login.html')
2
3
4
5
6
7
8
9
10
# CBV
from flask import Flask, views
app = Flask(__name__)
def test1(func):
def inner1(*args, **kwargs):
print('before1')
result = func(*args, **kwargs)
print('after1')
return result
return inner1
def test2(func):
def inner2(*args, **kwargs):
print('before2')
result = func(*args, **kwargs)
print('after2')
return result
return inner2
class UserView(views.MethodView):
methods = ['GET', "POST"] # 不写该类变量的话,默认只支持GET
# view = test2(test1(view)) --> view = test2(inner1) --> view = inner2
decorators = [test1, test2]
def get(self, pk):
print('get')
return 'get'
def post(self, pk):
print('post')
return 'post'
app.add_url_rule('/user/<int:pk>', view_func=UserView.as_view('user')) # 'user' 就是 endpoint
if __name__ == '__main__':
app.run()
"""GET请求和POST请求访问 http://127.0.0.1:5000/user/1 都会打印以下内容
before2
before1
post
after1
after2
"""
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# CBV源码
Flask整个CBV的源码逻辑 跟 Django的CBV 源码逻辑 并无出入, 一模一样!
as_view
-- view
-- 路由匹配成功后,加括号执行view -- view里做了两件事, 实例化当前视图类 + 执行dispatch方法 -
在dispatch方法中 反射执行了路由匹配的 视图函数!!
△ 注意: 在Flask的CBV里,还有个很好玩的地方: 可以给视图函数添加装饰器..
# 模版
注意: 若使用了蓝图, 那么 定义全局模板方法 的应用范围只有本蓝图!!
# 特殊装饰器-中间件
@app.before_request
、@app.after_request
能实现跟 Django中间件一样的执行流程!!
我实验过了, Flask的FBV、CBV都可以使用这两个特殊的装饰器!!
from flask import Flask, views
app = Flask(__name__)
@app.before_request
def f1():
print('f1')
@app.before_request
def f2():
if request.path == "/login": # !!读session会话保持,读白名单等
return
print('f2')
@app.after_request
def f10(response):
print('f10')
return response
@app.after_request
def f20(response):
print('f20')
return response
@app.route('/index')
def index():
print("index")
return "hello world"
if __name__ == '__main__':
app.run()
"""
f1
f2
index
f20
f10
"""
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
扩展:
@app.before_request
def f1():
print('f1')
2
3
等同于
def f1():
print('f1')
f1 = app.before_request(f1)
# app.before_request(f1) 这样写也可以,因为你看源码,它是把f1添加到一个列表中了..整个中间件过程用的是列表中的.返回的f1没用..
2
3
4
5
# 补充: threading.local
若多线程来, 它会为每个线程独立开辟一个小区域, 存储当前线程的值!!
Flask源码里没有用它, 但Flask基于线程ID自己实现了类似的功能!!