0%

创建项目

flask 项目不能像 django 那样通过命令行创建,所以直接在 pycharm 中新建 Flask 项目。

假如我们创建了一个名为 Demo 的项目,那么创建好的项目目录如下所示:

1
2
3
4
Demo
- static
- templates
- app.py

只有两个文件夹和一个 py 文件,真不愧是轻量级框架。

  • static:存放静态资源,如 css,js
  • templates:存放模板,类似 django
  • app.py:项目启动文件

然后我们就可以启动项目了。在启动项目之前,需要设置 Flask 的环境变量,打开终端,执行以下指令:

1
2
$env:FLASK_APP=app.py
$env:FLASK_ENV=development

linux 环境:

1
2
export FLASK_APP=app.py
export FLASK_ENV=development

app.py 就是项目的入口文件,名字依个人而异。

然后启动项目:

1
flask run
阅读全文 »

比如有如下目录结构:

1
2
3
4
5
6
7
root.py
- A
- __init__.py
- a.py
- B
- __init__.py
- b.py

root.py:

1
from A.a import class_a

a.py:

1
2
3
4
from B.b import class_b

class class_a:
pass

b.py:

1
2
3
4
from A.a import class_a

class class_b:
pass

此时运行 root.py 会发生报错:

ImportError: cannot import name ‘class_a’ from partially initialized module ‘A.a’ (most likely due to a circular import)

阅读全文 »

在程序中我们所写的函数大都不是单独完整的,在使用一个函数完成自身功能的时候,很可能需要同其他的部分进行交互,需要其他外部变量的支持,上下文就是给外部的变量赋值,使函数能正确运行。

Flask 提供了两种上下文,一种是应用上下文(Application Context),一种是请求上下文(Request Context)。

应用上下文和请求上下文都是存放到一个 LocalStack 的栈中的,在应用运行时框架底层会在每个请求进入的时候将请求上下文和应用上下文都推入栈中,因此,在视图函数中,不用担心上下文的问题。

阅读全文 »

装饰器的作用就是为函数添加额外的功能。

装饰器原理

< 函数+实参高阶函数+返回值高阶函数+嵌套函数+语法糖 = 装饰器 >

直接来看例子:

1
2
3
4
5
def x(fuc): # 参数为函数(实参高阶函数)
def y(): # 嵌套函数
fuc()
print("hai")
return y # 返回一个函数(返回值高阶函数)

其实,函数 x 就可以作为一个装饰器。

接下来用 x 来装饰另一个函数:

1
2
3
4
5
6
7
8
9
10
11
def x(fuc): # 参数为函数(实参高阶函数)
def y(): # 嵌套函数
fuc()
print("hai")
return y # 返回一个函数(返回值高阶函数)

def test(): # 被装饰函数
print('hello')

test = X(test)
test()

运行代码,结果依次输出 “hello”,”hi”。

阅读全文 »

module

表示当前操作的对象在哪个模块,即所在包的包名,若不在包中,则为”main“。

1
2
3
4
from A.B import C

c = C()
print(c.__module__) # A.B

class

表示当前操作的对象的类是什么。

1
2
3
4
from A.B import C

c = C()
print(c.__class__) # A.B.C

阅读全文 »

1
2
3
4
5
6
7
student = Student(id=id, name=name, age=age)
try:
db.session.add(student)
db.session.commit()
except:
# 事务回滚
db.session.rollback()

1
2
db.session.delete(user)
db.session.commit()
阅读全文 »

拥有 init.py 文件的文件夹被视为包(模块),可以通过 import 正常导入包内的文件,否则,会报 ImportError 错误。

当 import 包或包内模块的时候,会先执行 init.py 文件中的代码,因此可以通过 init.py 组织包内各个子模块,然后在包外文件导入它们时更加方便简洁。我们来看一个例子:

目录结构如下:

1
2
3
4
5
- app
- __init__.py
- add.py
- sub.py
- main.py
阅读全文 »

基础概念

设备像素或逻辑像素

指设备能控制显示的最小物理单位,意指屏幕上一个个的点。

CSS像素或设备独立像素

指CSS样式代码中使用的逻辑像素,即 px(在iPhone中单位为pt)。

像素密度(PPI)

指设备能控制显示的最小物理单位,意指屏幕上一个个的点(=设备像素或逻辑像素)。PPI 越高,分辨率也就越高。

像素比(DPR)

像素比 = 设备像素 / CSS像素。

rem

rem 是一个相对单位,区别于 em(相对于父亲的字体大小) ,它是相对于 html 的字体大小单位。


阅读全文 »

ArrayBuffer 表示二进制数据的原始缓冲区,该缓冲区用于存储各种类型化数组的数据。是最基础的原始数据容器,无法直接读取或写入, 需要通过其他方式来读写。如:

1
2
3
4
5
6
7
Int8Array             8位有符号整数
Uint8Array 8位无符号整数
Uint8ClampedArray 8位无符号整数,像素操作

Int16Array 16位有符号整数
Uint16Array 16位无符号整数
...
阅读全文 »

由于 js 无法对文件直接操作,所以通过 js 下载文件的原理是创建一个 标签,然后让其执行 click() 方法来进行下载。

具体代码如下:

1
2
3
4
5
6
// 假设 data 为后台返回的 ArrayBuffer
let link = document.createElement('a');
link.href = window.URL.createObjectURL(new Blob([data]));
link.download = file.name;
link.click();
window.URL.revokeObjectURL(str2ab(sm4_decrypt_str));

我们这里用到了 Blob 类,接下来就来讲一下 Blob 的用法。

阅读全文 »