Flask 学习

架构

常用的架构有以下两种方式:

  • 功能式
  • 分布式

功能式

简单来讲就是以功能来归类文件,比如静态文件放一个目录,模块文件放一个目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
yourapp/
__init__.py
static/
templates/
home/
control_panel/
admin/
views/
__init__.py
home.py
control_panel.py
admin.py
models.py

除了 yourapp/views/__init__.py,在yourapp/views/文件夹中的每一个.py文件都是一个蓝图。在yourapp/__init__.py 中,我们将加载这些蓝图并在我们的Flask()对象中注册它们。

特点:

  • 分类明确,很明显就知道去哪找哪种文件;
  • 适合小型项目;
  • 各功能之间联系紧密;

分布式

按照每一部分所属的蓝图来组织你的应用。比如A功能的静态文件、模块、视图都放在A的这一个大的目录下。就像一个国家有N个诸侯,每个诸侯管理自己的地盘,互不打扰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
yourapp/
__init__.py
admin/
__init__.py
views.py
static/
templates/
home/
__init__.py
views.py
static/
templates/
control_panel/
__init__.py
views.py
static/
templates/
models.py

在像上面列举的分区式结构,每一个yourapp/之下的文件夹都是一个独立的蓝图。所有的蓝图通过顶级的__init__.py注册到Flask()中。

特点:

  • 应用较为独立,仅共享配置和模型等等;
  • 更为灵活

综上所述一般绝大部分的项目就用功能式的架构就会满足需要了。

如何使用蓝图重构一个项目

Step 1:分区式还是功能式?
这个应用由关联较小的各部分构成。模板和静态文件不太可能在蓝图间共享,所以我们将使用分区式结构。
Step 2:分而治之
注意 在你对你的应用大刀阔斧之前,把一切提交到版本控制。你不会接受对任何有用的东西的意外删除。

接下来我们将继续前进,为我们的新应用创建目录树。从为每一个蓝图创建一个目录开始吧。然后整体复制views.py,static/和templates/到每一个蓝图文件夹。接着你可以从顶级目录删除掉它们了。

Step 3:大扫除
现在我们可以到每一个蓝图中,移除无关的视图,静态文件和模板。你在这一阶段的处境很大程度上取决于一开始你是怎么组织你的应用的。

最终结果应该是:每个蓝图有一个views.py包括了蓝图里的所有视图,没有两个蓝图对同一个路由定义了视图;每一个templates/文件夹应该只包括该蓝图所需的模板;每一个static/文件夹应该只包括该蓝图所需的静态文件。

注意 趁此机会消除所有不必要的import。很容易忽略掉他们的存在,但他们会拥塞你的代码,甚至拖慢你的应用。

Step 4:蓝图
在这一部分我们把文件夹转换成蓝图。关键在于__init__.py文件。作为开始,让我们看一下API蓝图的定义。

Step 5:大功告成
现在我们的应用已经比只有单个臃肿的views.py的时候更加模块化了。

总结:

  • 一个蓝图包括了可以作为独立应用的视图,模板,静态文件和其他插件。
  • 蓝图是组织你的应用的好办法。
  • 在分区式架构下,每个蓝图对应你的应用的一个部分。
  • 在功能式架构下,每个蓝图就只是视图的集合。所有的模板和静态文件都放在一块。
  • 要使用蓝图,你需要定义它,并在应用中用Flask.register_blueprint()注册它。
  • 你可以给一个蓝图中的所有路由定义一个动态URL前缀。
  • 你也可以给蓝图中的所有路由定义一个动态子域名。
  • 仅需五步走,你可以用蓝图重构一个应用。

一些有意思的事情

json和jsonify的差异

字符串转json对象,使用json.loads()

1
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
import json
# 字符串转json,注意(key与value必须是双引号)
str1 = '{"a":1, "b":"2"}'
j1 = json.loads(str1)
print(type(j1), j1) # <class 'dict'> {'a': 1, 'b': '2'}

str2 = '[{"a":1},{"a":"2"}]'
j2 = json.loads(str2)
print(type(j2), j2) # <class 'list'> [{'a': 1}, {'a': '2'}]
for obj in j2:
print(obj["a"]) # 1 2

# 可见通过json的loads方法可将标准json字符串转成字典对象或字典集合
# 下面是嵌套组合的字符串也可以通过loads方法转换
f = '{"a":1, "b": [{"b_1": "b1"}, {"b_1": "b1"}]}'
l = json.loads(f)
print(type(l), l) # <class 'dict'> {'a': 1, 'b': [{'b_1': 'b1'}, {'b_1': 'b1'}]}
print(l["b"], type(l["b"])) # [{'b_1': 'b1'}, {'b_1': 'b1'}] <class 'list'>

# 输出

<class 'dict'> {'a': 1, 'b': '2'}
<class 'list'> [{'a': 1}, {'a': '2'}]
1
2
<class 'dict'> {'a': 1, 'b': [{'b_1': 'b1'}, {'b_1': 'b1'}]}
[{'b_1': 'b1'}, {'b_1': 'b1'}] <class 'list'>

json对象转字符串,使用json.dumps()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import json

obj = {
"a": 1,
"b": "2"
}
objStr = json.dumps(obj)
print(type(objStr), objStr) # <class 'str'> {"a": 1, "b": "2"}
arr = [
{"a": 1},
{"a": "2"}
]
arrStr = json.dumps(arr)
print(type(arrStr), arrStr) # <class 'str'> [{"a": 1}, {"a": "2"}]

# 输出
<class 'str'> {"a": 1, "b": "2"}
<class 'str'> [{"a": 1}, {"a": "2"}]

通过jsonify()将dict转为json字符串

简单,快速是Flask自带的模块jsonify。 功能类似于json.dumps(),但是会把返回的Content-Type从text/html转换成带json特征的 application/json

1659598907405.png

总结:

  • json.loads() 把 json 字符串 转成 python 数据类型
  • json.load(python数据类型,文件句柄) 把 json 文件 转成 python 数据类型
  • json.dumps() 把 python 数据类型 转成 json 字符串
  • json.dump(文件句柄) 把 python 数据类型 写入到 json 文件中

个人倾向在flask项目中使用jsonify(),简捷。