• 【flask入门系列】Flask-SQLAlchemy的使用


    📋 个人简介

    • 💖 作者简介:大家好,我是阿牛,全栈领域新星创作者。😜
    • 📝 博主的个人网站:阿牛的博客小屋🔥
    • 🎉 支持我:点赞👍+收藏⭐️+留言📝
    • 📣 系列专栏:flask框架快速入门🍁
    • 💬格言:要成为光,因为有怕黑的人!🔥
      请添加图片描述

    前言

    上面一篇写了Flask-SQLAlchemy的安装与配置,这一篇写它的使用,还是基本的增删改查,说实话,又要学一波新内容,还是比较痛苦的,突然觉得用pymysql写原生sql还不错,最起码我会sql…,不说了,上了这条船就把他学完,比较好的是Flask-SQLAlchemy是通用的,不仅是flask中能用,其他项目也可以,不像django的orm是专属的!

    创建模型类

    数据库配置settings.py

    #设置连接数据库的url
    SQLALCHEMY_DATABASE_URI = 'mysql://root:ndh15593318163@127.0.0.1:3306/flaskdemo'
    
    # 动态追踪修改设置,如未设置只会提示警告,也就是说你在数据库修改的会在models中同步
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    
    • 1
    • 2
    • 3
    • 4
    • 5

    app.py

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    
    #从配置文件中settings加载配置
    app.config.from_pyfile('settings.py')
    
    # 实例化模型工具类对象,将app中的数据库配置加载进去
    db = SQLAlchemy(app)
    
    
    # 创建数据库模型类
    
    # 用户表
    class User(db.Model):
        __tablename__ = "flask_users"  #指明数据库的表名
        id = db.Column(db.Integer,primary_key=True)  #主键,默认自增
        name = db.Column(db.String(30),unique=True,nullable=False)
        email = db.Column(db.String(50),unique=True)
        password = db.Column(db.String(60))
        role_id = db.Column(db.Integer,db.ForeignKey("flask_roles.id"))
        # 外键,对应角色表的id(是从底层数据库角度考虑的)
    
    
    # 角色表
    class Role(db.Model):
        __tablename__ = "flask_roles"
        id = db.Column(db.Integer, primary_key=True)  # 主键,默认自增
        name = db.Column(db.String(30),unique=True,nullable=False)
    
        #由于用户表有外键对应到角色表,我们可以通过用户查询它对应的角色,但是我们怎么查询一个角色对应的用户呢?
        #db.relationshap可以解决
        # db.Column的是数据库表中实际真真要创建的列,db.relationshap对应的字段是数据库表中不存在的,
        # 即不是底层了,而是站在了模型类的角度,将两个模型类关联起来了,第一个参数为你要对应的模型类
        # 我们可以通过role(Role实例化的对象).users获取整个user对象
        # users = db.relationshap("User")
    
    
    
        # 同样对于user(User实例化的对象),我们要先拿到role_id,然后通过Role才能拿到角色信息,
        # 能不能直接通过user拿到整个role对象呢
        # relationshap的第二个参数backref可以反向给User添加一个虚的属性, user.role将获取整条纪录
        # backref离不开User里面的外键,和外键结合使用
        users = db.relationship("User",backref="role")
    
    • 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

    如上面代码,我们创建了两张表,重点理解db.relationshap(“User”,backref=“role”),关于处理外键这块理解不了也没有关系,在项目中完全可以用跨表查询的方式去完成!

    创建数据库表

    创建好模型类之后我们就要创建数据库表了,在django中我们可以用migrate指令快速创建,而在flask中要用这种指令需要装额外扩展,这里先不介绍这种扩展,我们先用最原始的方式学习!

    1.创建所有的表

    db.create_all()
    
    • 1

    2.清楚当前数据库所有表

    db.drop_all()
    
    • 1

    在这里插入图片描述
    在这里插入图片描述
    可以看到成功在数据库中生成了这两张表!

    添加保存数据

    1.添加单条数据

      #添加单条数据
        role1 = Role(name="admin")  #创建对象
        db.session.add(role1) # 用session记录对象任务
        db.session.commit()  # 提交任务到数据库中
    
        role2 = Role(name="stuff")  # 创建对象
        db.session.add(role2)  # 用session记录对象任务
        db.session.commit()  # 提交任务到数据库中
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.添加多条数据

    # 添加多条数据
        use1 = User(name="aniu1", email="1234561@qq.com",password="1234561",role_id=role1.id)
        use2 = User(name="aniu2", email="1234562@qq.com", password="1234562", role_id=role1.id)
        use3 = User(name="aniu3", email="1234563@qq.com", password="1234563", role_id=role2.id)
        use4 = User(name="aniu4", email="1234564@qq.com", password="1234564", role_id=role2.id)
        # 以列表形式一次添加多条数据
        db.session.add_all([use1,use2,use3,use4])
        db.session.commit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    一次性运行这些,可以看到两张表数据都添加成功!
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    数据库查询

    常用的SQLAlchemy查询执行器看下图:
    请添加图片描述

    常用的SQLAlchemy查询过滤器:
    在这里插入图片描述
    下面我把一些常见的查询的demo附上,只要sql语句过关,这些上层的封装挤记一记就OK!

     # 查询所有用户数据
        ros = Role.query.all() #返回列表, 元素为模型对象
        print(ros[0].name)
    
        # 查询第1个用户
        ro = Role.query.first() #返回模型对象 / None
        print(ro)
    
        # 除了这两种方式,还有SQLAlchemy的查询方式
        db.session.query(Role).all()
        db.session.query(Role).first()
    
        #根据id查询
        User.query.get(1)  #返回模型对象 / None
    
        # 等值过滤器,关键字实参设置字段值,返回BaseQuery对象
        # BaseQuery对象可以续接其他过滤器/执行器  如 all/count/first等
        User.query.filter_by(id=2).all()
        User.query.filter_by(id=2,name="aniu2").all()
    
        # 复杂过滤器,参数为比较运算 / 函数引用等,返回BaseQuery对象
        User.query.filter(User.id == 3).first()
        print(User.query.filter(User.id == 3,User.name == "aniu3").first())
    
        # 查询名字结尾字符为1的所有用户[开始 / 包含]  name == aniu1
        User.query.filter(User.name.endswith("1")).all()
        User.query.filter(User.name.startswith("a")).all()
        User.query.filter(User.name.contains("n")).all()
        print(User.query.filter(User.name.like("a%iu%")).all())  # 模糊查询
    
        #filter_by和filter中有多个参数代表多条件查询的and
        # 例如:查询User.name以a开头,以1结尾的两种方式
        User.query.filter(User.name.startswith("a"),User.name.endswith("1")).all()
        # 或者
        from sqlalchemy import and_
        User.query.filter(and_(User.name.startswith('a'), User.name.endswith("1"))).all()
    
    
        #对于and,我们可以不用导入and_,但对于or,我们必须导入or_
        from sqlalchemy import or_
        User.query.filter(or_(User.name.startswith('a'), User.email.endswith("@qq.com"))).all()
    
        # 查询名字不等于aniu1的所有用户[2种方式]
        from sqlalchemy import not_
        User.query.filter(not_(User.name == 'aniu1')).all()
        User.query.filter(User.name != 'aniu1').all()
    
        # 查询id为[1, 2, 3]的用户
        print(User.query.filter(User.id.in_([1, 2, 3])).all())
    
        # 查询第2-4位的数据   2 3 4
        User.query.offset(1).limit(3).all()
    
        # 按id倒叙查询所有用户
        User.query.order_by(User.id.desc()).all()
    
        # 分组查询要用db.session.query,且要 from sqlalchemy import func
        # 按角色分组查询每一角色对应的用户数
        from sqlalchemy import func
        db.session.query(User.role_id,func.count(User.role_id)).group_by(User.role_id)
    
        # 只查询所有人的姓名和邮箱  优化查询   User.query.all()  # 相当于select *
        from sqlalchemy.orm import load_only
    
        data = User.query.options(load_only(User.name, User.email)).all()  # flask-sqlalchemy的语法
        for item in data:
            print(item.name, item.email)
    
        data = db.session.query(User.name, User.email).all()  # sqlalchemy本体的语法
        for item in data:
            print(item.name, item.email)
    
    • 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

    关联查询

     # 关联查询
        # --- 查询用户对应的角色
    
        #法一:跨表查询
        user = User.query.get(1)
        role = Role.query.get(user.role_id)
        print(role.name)
    
        # 法二:和 backref = "role" 有关,结合外键
        user = User.query.get(1)
        role = user.role
        print(role.name)
    
        # --- 查询角色对应的用户
        # 法一:跨表查询
        role = Role.query.get(1)
        users = User.query.filter_by(role_id=role.id).all()
        print(users)
    
        # 法二:和 users = db.relationshap("User") 有关
        role = Role.query.get(1)
        users = role.users
        print(users)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    数据的更新

    flask-sqlalchemy 提供了两种更新数据的方案

    • 先查询, 再更新
      对应SQL中的 先select, 再update — 查询和更新分两条语句, 效率低如果并发更新, 可能出现更新丢失问题(Lost Update)!
    • 基于过滤条件的更新 (推荐方案)
      对应SQL中的 update xx where xx = xx (也称为 update子查询 ) — 一条语句, 被网络IO影响程度低, 执行效率更高;查询和更新在一条语句中完成, 单条SQL具有原子性, 不会出现更新丢失问题;会对满足过滤条件的所有记录进行更新, 可以实现批量更新处理!
     # 先查询,再修改
        user = User.query.get(1)
        user.name = "aniu"
        db.session.commit()
    
     #基于过滤条件的更新(推荐方案) filter 或者 filter_by
        # update里面跟一个字典,字典里写你要更新的字段的键值
        User.query.filter(User.name == 'aniu').update({'name': "aniu1"})
        db.session.commit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    再修改回来
    在这里插入图片描述

    数据的删除

    类似更新数据, 也存在两种删除数据的方案!

    • 先查询, 再删除
      对应SQL中的 先select, 再delete — 查询和删除分两条语句, 效率低!
    • 基于过滤条件的删除 (推荐方案)
      对应SQL中的 delete xx where xx = xx (也称为 delete子查询 ) — 一条语句, 被网络IO影响程度低, 执行效率更高;会对满足过滤条件的所有记录进行删除, 可以实现批量删除处理!
      # 先查询,再删除
        user = User.query.get(1)
        db.session.delete(user)
        db.session.commit()
    
      # 基于过滤条件的删除(推荐方案) filter 或者 filter_by
        User.query.filter(User.name == 'aniu1').delete()
        db.session.commit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    结语

    如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。

    🏰系列专栏
    👉软磨 css
    👉硬泡 javascript
    👉前端实用小demo

  • 相关阅读:
    Linux文件I/O
    ROS 环境使用第三方动态链接库(.so)文件
    案例分享 生产环境逐步迁移至k8s集群 - pod注册到consul
    I.MX6ULL ARM驱动开发---块设备驱动
    Python爬虫实战(七):某讯较真辟谣小程序爬虫
    Javascript基于protobufjs接入protobuf
    智慧学习环境移动智能终端零信任安全机制改进方案
    vivado查看报告和消息5
    MySQL MHA高可用配置及故障切换
    Kubernetes实战(一)-二进制部署Kubernetes集群
  • 原文地址:https://blog.csdn.net/qq_57421630/article/details/126062672