记录Flask-Sqlalchemy使用过的查询

在使用Flask开发的时候,用到Flask-Sqlalchemy进行数据库操作,作为数据库操作重要的部分,查询语句的设计直接关系到网站性能,真实体验到操作的重要性。

本片文章主要记录Flask-Sqlalchemy查询操作,也是开发工作中使用过的在此做个记录,先定义多对多的关系,方便举栗子,这是开发中的使用的例子,也可以理解成一般的多对多关系。

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
)

0x01 简单操作

普通查询

  • 根据主键(id)获取某一标签
    1
    tag = Tags.query.get(id)
  • 获取所有的标签
    1
    tags = Tags.query.all()
  • 根据非主键获取某一标签(name)
    1
    tag = Tags.query.filter(Tags.name=='xxx').first()
    2
    tag = Tags.query.filter_by(name='xxx').first()  #另种写法
  • 根据创建时间倒序,获取所有标签(desc)
    1
    tags = Tags.query.order_by(Tags.create_time.desc())
  • 获取所有标签的数量(count)
    1
    count = Tags.query.count()
  • 获取10个标签
    1
    tags = Tags.query.limit(10)
  • 切片查询,获取标签的1-10(多用于分页)(slice)
    1
    tags = Tags.query.slice(1,11)
  • 查询标签name中带有xxx的某一标签模糊查询(like)
    1
    tag = Tags.query.filter(Tags.name.like("%xxx%")).first()
  • 查询标签name中包含xxx的某个标签(contains)
    1
    tag = Tags.query.filter(Tags.name.contains('xxx')).first()
  • 查询标签name的小写等于xxx的标签(func.lower)
    1
    from sqlalchemy import func 
    2
    tag = Tags.query.filter(func.lower(Tags.name)=='xxx').first()
  • 查询标签表name一列(with_entitles)
    1
    names = Tags.query.with_entitles(Tags.name).all()
  • 查询标签表name一列去重(distinct)
    1
    names = Tags.query.with_entitles(Tags.name).distinct().all()
  • 查询标签name以x开头的所有标签(startswith)
    1
    tags = Tags.query.filter(Tags.name.startswith('x')).all()

通过关系查询

  • 查询标签name=xxx下所有的漏洞库
    1
    vuls = Tags.query.filter_by(name='xxx').vuls
  • 查询漏洞库name=xxx的所有标签
    1
    tags = Vuls.query.filter_by(name='xxx').tags
  • 将标签name=xxx,添加到name=yyy的漏洞库上
    1
    tag = Tage.query.filter_by(name='xxx').first()
    2
    tags = Vuls.query.filter_by(name='xxx').tags
    3
    tags.append(tag)

    其实多对多的操作,就是list操作,多的方面是一个列表,对应的增删改,及为列表的增删改

0x02 进阶操作

时间查询

  • 查询指定创建日期的所有标签(extract)
    1
    from sqlalchemy import extract
    2
    from datetime import date
    3
    today = date.today()
    4
    tags = Tags.query.filter(extract('year', Tags.create_time)==today.year,
    5
                            extract('month', Tags.create_time)==today.month,
    6
                            extract('day', Tags.create_time)==today.day).all()
  • 查询某个时间段之间的所有创建的标签(between)
    1
    from sqlalchemy import between
    2
    tags = Tags.query.filter(Tags.create_time.between('1990-01-01','1990-01-02'))

多条件查询

  • 查询name=xxx并且create_time=xxx的某个标签(and_)
    1
    from sqlalchemy import and_
    2
    tags = Tags.query.filter(and_(Tags.name=='xxx', Tags.create_time=='xxx')).first()
  • 查询name=xxx或者create_time=xxx的某个标签(or_)
    1
    from sqlalchemy import or_
    2
    tags = Tags.query.filter(or_(Tags.name=='xxx', Tags.create_time=='xxx')).first()
  • 查询标签name在[‘xxx’,’yyy’,’zzz’]列表中的所有(in_)
    1
    tags = Tags.query.filter(Tags.name.in_(['xxx','yyy','zzz'])).all()
  • 查询标签name不是以x开头的所有标签(not_)
    1
    from sqlalchemy import not_
    2
    tags = Tags.query.filter(not_(Tags.name.startswith('x'))).all()

工作中遇到的

  • 在开发观星资产中,不定查询条件(text)
    1
    from sqlalchemy import text
    2
    dict = request.args.to_dict()
    3
    for k, v in dict.items():
    4
        asert_obj = asert_obj.filter(text("%s = '%s'" % (k, v)))

    0x03 总结

    进记录下使用过的查询,以后会继续更新在工作中用到的查询。