[TOC]

0x00 模型(Models)

描述:Flask 模型由于 Flask 默认并没有提供任何数据库操作的API,我们可以选择任何合适自己项目的数据库来使用,可以采用原生的语句实现也可以采用ORM框架(SQLAlchemy / MongoEngine 扩展库) 实现;

Q: 原始SQL有何缺点?

答: 代码利用率低且条件复杂代码语句越长,有狠毒相似语句一些SQL是在业务逻辑中拼出来的修改需要了解业务逻辑,并且可能会导致一些SQL安全问题, 优点是性能好速度快;

Q: 使用ORM对象优点?

答: 实际上将对象的操作转换为原生的SQL,我们并不需要关注我们使用的是什么数据库只需要设计出模型Model即可;

  • 1.易用性可以有效减少重复SQL
  • 2.性能损耗少
  • 3.设计灵活,可以轻松的实现复杂查询
  • 4.移植性好

SQLAlchemy 连接使用流程:

  • 1.指定数据库配置app.config['SQLALCHEMY_DATABASE_URI']=DB_URI以及禁止对象追踪修改app.config['SQLALCHEMY_TRAKE_MODIFICATIONS']=False

  • 2.通过懒加载的方式初始化SQLalchemy()扩展;

  • 3.数据库的使用创建模型class Person(db.model)

  • 4.数据库操作

    1
    2
    3
    4
    5
    创建数据库: db.create_all()
    删除数据库:db.drop_all()
    数据更新插入: db.session.add(Object) / db.session.add_all(List)
    数据删除: db.session.delete(Object)
    数据提交: db.session.commit()
  • 5.数据库查询:
    SQLalchemy插件查询函数: \Python37-32\lib\site-packages\sqlalchemy\orm\query.py
    1
    2
    3
    4
    5
    6
    # 查询数据结果集
    # 模型类.query.查询方法
    Student.query.frist()
    Student.query.get(主键ID) # 返回Student对象主键数据否则None
    Student.query.get_or_404(主键索引) # 找寻到返回数据否则返回404
    Student.query.all() # 查询所有
  • 6.蓝图视图自定义模板与静态资源路径:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # - 模板/静态路径默认在Flask(app)创建的路径下,或者采用以下方式自定义模板路径
    template_folder = "../templates"
    static_folder = "../static"
    url_prefix='/db' # 蓝图统一前缀必须以/打头

    # 例如
    # 方式1-Flask app 创建时指定
    Day3\App\__init__.py
    # 获取Flask-APP对象自定义template与static目录
    app = Flask(__name__, template_folder="../templates", static_folder = "../static")

    # 方式2-Flask 蓝图创建时指定
    from flask import Blueprint,redirect,url_for
    demo1 = Blueprint('demo1',__name__, template_folder="../templates",url_prefix='/db')


    #- 模板中也能使用反向解析蓝图(与Python代码一致)
    def redirect():
    return url_for('demo1.get_student',id=1) # blue.get_student 是蓝图.函数
  • 7.静态资源软编码在Flask中默认支持的,默认路径在和Flask同级别的static中静态资源是有路由的可以使用filename参数指定静态文件
    1
    2
    3
    4
    5
    6
    <!-- 原始 -->
    <link rel="stylesheet" href="/static/css/index.css"/>

    <!-- url_for 方式 -->
    <!-- # 在DebugToor中endpoint是static的 -->
    <link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}"/>
  • 8.关系型数据库最多使用的三种数据库类型: 数字 INT、字符串 CHAR、时间日期 DATETIME

例如:将SQL中创建表的语句转换成为SQLAlchemy模型

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
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
54
55
56
/** 记录表**/
CREATE TABLE record(
rid INT PRIMARY KEY NOT NULL,
uid INT NOT NULL,
starttime TIMESTAMP NOT NULL,
endtime TIMESTAMP NOT NULL,
applytime TIMESTAMP NOT NULL,
context CHAR(255) NOT NULL,
daytype CHAR(32) NOT NULL,
recordtime TIMESTAMP NOT NULL,
ipaddr CHAR(255) NOT NULL,
);


class Record(db.Model):
__tablename__ = 'record' #表名
rid = db.Column(db.Integer, primary_key=True) # 记录类型
uid = db.Column(db.Integer, index=True) # 用户标识
daytype = db.Column(db.String) # 工作日、周末、节假日
starttime = db.Column(db.DateTime, default=datetime.datetime.utcnow) # 开始时间
endtime = db.Column(db.DateTime, default=datetime.datetime.utcnow) # 结束时间
applytime = db.Column(db.DateTime, default=datetime.datetime.utcnow) # 申请时间
recordtime = db.Column(db.DateTime, default=datetime.datetime.utcnow) # 提交记录时间
ipaddr = db.Column(db.String) # 提交者IP信息
context = db.Column(db.String) # 工作加班内容或者申请备注


-- #####################################
/** 用户表 **/
CREATE TABLE user(
uid INT PRIMARY KEY NOT NULL,
name VARCHAR(32) NOT NULL,
gender INT2 NOT NULL,
yearsofwork INT,
address VARCHAR(255)
);

class User(db.Model):
__tablename__ = 'user' #表名
uid = db.Column(db.Integer, primary_key=True, index=True) # 用户表示
name = db.Column(db.String) # 用户姓名
gender = db.Column(db.Integer) # 用户性别(0,1)
yearsofwork = db.Column(db.Integer) # 工作年限
address = db.Column(db.String) # 工作地点

-- #####################################
/** 类型表 **/
CREATE TABLE recordtype (
rid INT PRIMARY KEY NOT NULL,
name TEXT NOT NULL
);

class RecordType(db.Model):
__tablename__ = 'recordtype' #表名
rid = db.Column(db.Integer, primary_key=True, index=True) # 记录标识
name = db.Column(db.Text) # 记录名称

基础实例:

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
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Day3\App\views\work\main.py
from flask import Blueprint,render_template
from App.models import db,User,Record,RecordType

worker = Blueprint('worker',__name__)

@worker.route('/dballinit/')
def create_db():
db.create_all();
return '创建成功'


@worker.route('/dballdrop/')
def drop_db():
db.drop_all()
return '删除成功'

# 增
@worker.route('/userinsert/')
def insert_user():
peoples = []

for i in range(6):
people = User()
people.name = "测试人员%d" % i
people.gender = 0 if i % 2 else 1
people.yearsofwork = i
people.address = "办公位置: 70{}".format(i)
peoples.append(people)

db.session.add_all(peoples)
db.session.commit()

return 'Insert User Successful!'

# 查
@worker.route('/userget/<int:id>')
def query_user(id):
count = User.query.count()
first = User.query.first()
middle = User.query.get_or_404(3)
custom = User.query.get(id)

res1 = User.query.filter_by(gender=0,yearsofwork=3).first() # 简单条件过滤
res2 = User.query.filter(User.name.startswith('测试人员')).limit(2).all() # 复杂条件过滤

result = User.query.all() # 返回该表的所有数据

if middle != None:
print("类型", type(count), " 总数据条数: " , count)
print("类型", type(first), "第一行数据: ",first)
print("类型", type(middle), "索引为3得数据(不存在则返回404): ", middle)
print("类型", type(custom), "索引为 {} 得数据: ".format(id), custom)
print("Index: {}, Name: {}, Gender: {}, Address: {} \n".format(custom.uid, custom.name, custom.gender, custom.address))

print("\nquery.filter_by 类型: ",type(res1))
print("Index: {}, Name: {}, Gender: {}, Address: {} \n".format(res1.uid, res1.name, res1.gender, res1.address))

print("query.filter 类型 : ",type(res2))
print("all 类型: \n",type(result))

return render_template('User/query.html',title="User query",result=result)

else:
return 'Index not found!'


# 删
@worker.route('/userdelete/')
def delete_query():
obj = User.query.filter_by(name="测试人员5").first()
db.session.delete(obj)
db.session.commit()

return "测试人员5 - Delete Success"


# 改
@worker.route('/userupdate/')
def update_user():
obj = User.query.filter_by(yearsofwork=3).first()
obj.name = "WeiyiGeek"
obj.address = "https://weiyigeek.top"

db.session.add(obj)
db.session.commit();

return '<script>alert("修改成功");location.href="/userget/"</script>'

# 更新所有的数据
@worker.route('/userallupdate/')
def update_all():
obj = User.query.all()

for i in obj:
i.name = "WeiyiGeek's"

db.session.add_all(obj)
db.session.commit()

return '<script>alert("修改成功");location.href="/userget/"</script>'

执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# (1) 数据插入
http://127.0.0.1:8000/userinsert/
# Insert User Successful!


# (2) 数据查询
http://127.0.0.1:8000/userget/
uid name gender yearsofwork address
1 测试人员0 1 0 办公位置: 700
2 测试人员1 0 1 办公位置: 701
3 测试人员2 1 2 办公位置: 702
4 测试人员3 0 3 办公位置: 703
5 测试人员4 1 4 办公位置: 704
6 测试人员5 0 5 办公位置: 705

# (3) 数据删除
http://127.0.0.1:8000/userdelete/
测试人员5 - Delete Success

# (4) 数据更新
http://127.0.0.1:8000/userupdate/
http://127.0.0.1:8000/userallupdate/

WeiyiGeek.SQL-Query

WeiyiGeek.SQL-Query

帮助文档:

JSON - https://www.cnblogs.com/lanston1/p/11024147.html