Flask-Sqlalchemy简单使用

在开发过程中需要借助数据库来存储相关信息,在关系型数据库中可能就需要关系来处理事物之间的逻辑,而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的进阶操作,比如关系操作、复杂查询等等。