在开发过程中需要借助数据库来存储相关信息,在关系型数据库中可能就需要关系来处理事物之间的逻辑,而Flask
中的Flask-Sqlalchemy
使用orm
来实现对象关系映射,这个对于不熟悉原生sql语句的开发者来说,真是福音。本片文章主要记录一些简单的操作。
开发漏洞靶场的时候,使用重新记录下相关操作,从数据库配置、数据库模型设计以及迁移、数据增删改查等方面记录整个流程。
0X01 数据库配置
在开发这套系统的时候,使用的
mysql
数据库,而Flask-Sqlalchemy
支持多种关系型数据库。
这里记录下使用Flask-Sqlalchemy
配合mysql
相关配置
简单Flask项目,我习惯的文件结构如下:
下面所写的文件基本按照此文件结构,这是一个简单的项目:诗词名句网获取展示 有兴趣可以踩踩
config.py
1 | # mysql设置 |
2 | import pymysql |
3 | MYSQL_HOST = 'xxx' #host |
4 | MYSQL_PORT = 3306 #port |
5 | MYSQL_DATABASE = 'xxx' #db_name |
6 | MYSQL_USERNAME = 'xxx' #db_username |
7 | MYSQL_PASSWORD = 'xxx' #db_password |
8 | |
9 | SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(MYSQL_USERNAME, MYSQL_PASSWORD, |
10 | MYSQL_HOST, MYSQL_PORT, |
11 | MYSQL_DATABASE) |
12 | SQLALCHEMY_TRACK_MODIFICATIONS = False #是否追踪对象的修改 |
13 | SQLALCHEMY_COMMIT_ON_TEARDOWN = False #每次请求结束后都会自动提交数据库中的变动 |
14 | SQLALCHEMY_POOL_SIZE = 100 #数据库连接池的大小。默认是引擎默认值(通常 是 5 ) |
15 | SQLALCHEMY_MAX_OVERFLOW = 20 #控制连接池达到最大大小后还可以创建的连接数 |
16 | SQLALCHEMY_ECHO = False #是否输出stderr的语句 |
17 | SQLALCHEMY_POOL_RECYCLE = 90 #多少秒后自动回收连接 |
上面基本上涵盖了所有关于Flask-Sqlalchemy
的配置,下面就需要将Flask-Sqlalchemy
初始化app。这部分,我的习惯创建exts.py
进行SQLAlchemy
类的实例,这样会解决循环导入的问题
exts.py
1 | from flask_sqlalchemy import SQLAlchemy |
2 | db = SQLAlchemy() |
然后在app.py
中在导入db
进行初始化app
app.py
1 | from exts import db |
2 | db.init_app(app) |
这样就基本完了相关配置,这里的代码只是其中核心部分
0x02 数据库模型设计以及迁移
因为作为简单的例子,不必要的字段就不进行写了,在设计多对多的关系时,我的习惯就是创建中间表进行关联,这里展示模型设计。
models.py
1 | from exts import db |
2 | import datetime |
3 | |
4 | class Tags(db.Model): #标签表 |
5 | ''' |
6 | 漏洞的标签:id、名称、创建时间 |
7 | ''' |
8 | __tablename__ = 't_tags' |
9 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) |
10 | name = db.Column(db.String(50), nullable=True, comment='漏洞标签名称') |
11 | create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='加入时间') |
12 | vuls = db.relationship('Vuls', secondary=vul_tag, backref='tags') # 设置关系,通过中间表`t_vul_tag`实现 |
13 | |
14 | class Vuls(db.Model): |
15 | ''' |
16 | 靶场漏洞库 |
17 | ''' |
18 | __tablename__ = 't_vuls' |
19 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) #uuid |
20 | name = db.Column(db.String(255), nullable=True, comment='漏洞名称') |
21 | create_time = db.Column(db.DateTime, default=datetime.datetime.now, comment='加入时间') |
22 | |
23 | vul_tag = db.Table( #中间表,表名`t_vul_tag` |
24 | 't_vul_tag', |
25 | db.Column('t_vul_id', db.Integer, db.ForeignKey('t_vuls.id'), primary_key=True), |
26 | db.Column('t_tag_id', db.Integer, db.ForeignKey('t_tags.id'), primary_key=True) |
27 | ) |
这样就可以实现题目和标签之间多对多的关系。
模型设计好了,就需要映射到数据库中实实在在的表了,通常习惯创建manages.py
文件来写些方便的操作和进行数据库迁移,这里仅进行记录如何进行数据库迁移。
manages.py
1 | # -*- coding: UTF-8 -*- |
2 | __author__ = 'Joynice' |
3 | |
4 | from flask_migrate import Migrate, MigrateCommand |
5 | from flask_script import Manager |
6 | from apps.admin.models import Upload_Log |
7 | from app import create_app |
8 | from exts import db |
9 | |
10 | app = create_app() |
11 | |
12 | manager = Manager(app) |
13 | Migrate(app, db) |
14 | manager.add_command('db', MigrateCommand) |
15 | |
16 | if __name__ == '__main__': |
17 | manager.run() |
基本上就这样写就可以,
然后运行以下命令进行数据库的迁移
1 | python manages.py db init #初始化 |
2 | python manages.py db migrate #迁移 |
3 | python manages.py db upgrade #生成 |
运行完上述命令后,就会在数据库中生成三个表,就可以继续下面的操作了。
0x03 数据库增删改查
使用Flask-Sqlalchemy
进行增删改查非常的方便,不需要设计原生的sql语句,只需要对模型操作就可以了,以题目-标签为例子,进行增删改查操作。
- 增
- 增加标签
1
from exts import db
2
from models import Tags
3
tag = Tags(name='xxx', create_time='xxx')
4
db.session.add(tag)
5
db.session.commit()
- 添加题目
1
from exts import db
2
from models import Vuls
3
vul = Vuls(name='xxx', create_time='xxx')
4
db.session.add(vul)
5
db.session.commit()
- 增加标签
- 删
删除标签(id为1):删除标签的时候多先进行查询再进行删除1
from exts import db
2
from models import Tags
3
tag = Tags.query.get(1) #这种查询方法只是试用对`主键`查询
4
db.session.delete(tag)
5
db.session.commit()
- 改
更改标签name=’ceshi’:修改操作也多在查询之后进行,这里也对id=1的数据修改1
from exts import db
2
from models import Tags
3
tag = Tags.query.get(1) #这种查询方法只是试用对`主键`查询
4
tag.name = 'ceshi'
5
db.session.commit()
- 查
查的话上面操作已经有体现了
这片文章仅记录下简单的Flask-Sqlalchemy
的流程,以后会对更新一些文章关于Flask-Sqlalchemy
的进阶操作,比如关系操作、复杂查询等等。