zoukankan      html  css  js  c++  java
  • Flask—05-理解掌握flask数据模型(01)

    数据模型

    数据库回顾

    • 分类:
      • 关系型数据库:MySQL、sqlite、…
      • 非关系型数据库:Redis、MongoDB、…
    • 操作:
      • 执行原生SQL语句,每次都需要拼接SQL语句,非常繁琐而且特别容易出错。
      • ORM(对象关系映射),使用ORM可以通过对对象的操作完成对数据库的操作。

    flask-sqlalchemy

    • 说明:其实是sqlalchemy扩展库在flask中的移植库,通过了绝大多数关系型数据库的支持(ORM)

    • 安装:pip install flask-sqlalchemy

    • 连接地址配置:

      • 名称:SQLALCHEMY_DATABASE_URI
      • 格式:
        • sqlite:sqlite:/// + 数据库文件名
        • MySQL:数据库名+驱动名://用户名:密码@主机:端口/数据库
    • 使用:

      # 配置数据连接地址
      base_dir = os.path.dirname(__file__)
      database_uri = 'sqlite:///' + os.path.join(base_dir, 'data.sqlite')
      app.config['SQLALCHEMY_DATABASE_URI'] = database_uri
      # 禁止数据的修改追踪(需要消耗资源)
      app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
      
      # 创建数据库操作对象
      db = SQLAlchemy(app)
      
      # 设计模型类
      class User(db.Model):
          # 表名默认会将模型名转为小写加下划线的形式
          # 如:UserModel => user_model
          # 指定表名
          __tablename__ = 'users'
          id = db.Column(db.Integer, primary_key=True)
          name = db.Column(db.String(20), unique=True)
          email = db.Column(db.String(32), unique=True)
      
    • 数据表操作

      @app.route('/create/')
      def create():
          # 创建数据表
          db.create_all()
          return '数据表已创建'
      
      @app.route('/drop/')
      def drop():
          db.drop_all()
          return '数据表已删除'
      
      # 添加终端命令,完成数据表的创建
      @manager.command
      def createall():
          # 先删除原来的,副作用很大
          db.drop_all()
          # 然后再创建
          db.create_all()
          return '数据表已创建'
      
      # 添加终端命令,完成数据表的删除
      @manager.command
      def dropall():
          if prompt_bool('您确定要删库跑路吗?'):
              db.drop_all()
              return '数据表已删除'
          return '删库有风险,操作需谨慎!'
      

      执行终端命令:python manage.py createall,即可创建数据表

    数据库迁移

    • 说明:将数据模型的更改应用到数据表的操作叫数据库迁移。flask-migrate就是专门做迁移的扩展库。

    • 安装:pip install flask-migrate

    • 使用:

      from flask_migrate import Migrate
      
      # 创建数据库迁移对象
      migrate = Migrate(app, db)
      
      # 将迁移命令添加到终端
      manager.add_command('db', MigrateCommand)
      
    • 迁移:

      • 初始化,只需要一次,创建用户存放迁移脚本的目录及相关文件。
      python manage.py db init
      
      • 根据数据模型与数据表,生成迁移脚本。
      python manage.py db migrate
      
      • 执行迁移脚本
      python manage.py db upgrade
      
    • 提示:

      • 初始化操作只需要一次,以后生成迁移脚本与执行迁移脚本循环执行即可完成数据库的迁移。
      • 不是每次迁移都会成功,迁移出错时需要手动解决。

    CURD操作

    • 增加数据

      # 设置自动提交操作,请求结束时无论如何都会提交
      app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
      
      # 增加数据
      @app.route('/insert/')
      def insert():
          # 创建对象
          # jie = User(name='八戒', email='bajie@163.com', age=30)
          # hou = User(name='猴哥', email='houge@163.com', age=20)
          # 保存到数据库,只能保存一条数据
          # db.session.add(hou)
      
          bei = User(name='贝贝', email='bei@163.com', age=28)
          jing = User(name='晶晶', email='jing@163.com', age=18)
          huan = User(name='欢欢', email='huan@163.com', age=22)
          ying = User(name='迎迎', email='ying@163.com', age=23)
          ni = User(name='妮妮',email='ni@163.com',
          age=20)
      
          # 保存到数据库,一次性保存多条数据
          db.session.add_all([bei, jing, huan, ying, ni])
      
          # 提交操作,若没有设置自动提交,每次执行操作都需要手动提交一次
          # db.session.commit()
      
          return '数据已添加'
      
    • 查询数据

      # 查询操作
      @app.route('/select/<uid>/')
      def select(uid):
          # 根据主键进行查询,找到返回对象,没找到返回None
          user = User.query.get(uid)
          if user:
              return user.name
          return '查无此人'
      
    • 修改数据

      # 修改数据
      @app.route('/update/<uid>/')
      def update(uid):
          user = User.query.get(uid)
          if user:
              user.email = 'xxx@163.com'
              # 再次添加到数据库即可
              db.session.add(user)
              return '数据已修改'
          return '查无此人'
      
    • 删除数据

      # 删除数据
      @app.route('/delete/<uid>/')
      def delete(uid):
          user = User.query.get(uid)
          if user:
              db.session.delete(user)
              return '数据已删除'
          return '查无此人'
      

    模型设计参考

    • 常见的字段类型

      字段类型python类型说明
      Integer int 整型(32)
      SmallInteger int 整型(16)
      BigInteger int/long 整型(64)
      Float float 浮点型
      String str 变长字符串
      Text str 不受限制的文本
      Boolean bool 布尔值,True/False
      Date datetime.date 日期
      Time datetime.time 时间
      DateTime datetime.datetime 日期时间
      Interval datetime.timedelta 时间间隔
      PickleType pickle.dumps() 使用pickle模块序列化后的python对象
      LargeBinary bytes 任意大的二进制数据
    • 常见字段选项

      选项说明
      primary_key 是否作为主键索引,默认为False
      autoincrement 是否设置字段自增,默认为False
      unique 是否作为唯一索引,默认为False
      index 是否作为普通索引,默认为False
      nullable 字段是否可以为空,默认为True
      default 设置默认值
    • 总结:

      • 插入数据可以不传值的情况:自增的字段、可以为空的字段、有默认值的字段
      • 使用flask-sqlalchemy时每个模型都需要有一个主键,通常主键字段名称为id
      • 数据模型类名与数据表中的名字
        • 默认:会将模型名转换为小写加下划线的方式,如:UserModel => user_model
        • 指定:通过类属性__tablename__指定表名

    各种查询

    • 说明:在数据库的操作中,绝大多数都是查询操作,而且这些操作都是通过方法来实现的。

    • 常见操作:

      操作说明
      get 根据主键查询,查到返回对象,没查到返回None
      get_or_404 根据主键查询,查到返回对象,没查到报404错
      first 返回第一条数据,没有时返回None
      first_or_404 返回第一条数据,没有时报404错
      all 查询所有数据组成的列表
      limit 限制结果集数量,返回时查询对象
      offset 结果集偏移数量,返回时查询对象
      order_by 排序,指定字段后,默认按升序排序(asc),降序(desc),可以指定多个字段
      count 统计个数
    • 聚合函数:max、min、sum、avg、count

      from sqlalchemy import func
      
      @app.route('/query/')
      def query():
          # 聚合函数
          # max_age = db.session.query(func.max(User.age)).scalar()
          max_age = db.session.query(func.min(User.age)).scalar()
          return str(max_age)
      
    • 指定条件查询

      @app.route('/query/')
      def query():
          # 指定等值条件
          # users = User.query.filter_by(age=18).all()
          # 指定任意条件
          users = User.query.filter(User.age > 18).all()
          return ','.join(u.name for u in users)
      

    filter条件查询

    • 关系

      >, __gt__:大于
      示例:     # users = User.query.filter(User.age > 20).all()
              # 等价于上式
              users = User.query.filter(User.age.__gt__(20)).all()
      >=,__ge__:大于等于
      <, __lt__:小于
      <=,__le__:小于等于
      ==,__eq__:等于
      !=,__ne__:不等于
      
    • 范围

      users = User.query.filter(User.id.between(1, 3)).all()
      users = User.query.filter(User.id.in_((1, 3, 5))).all()
      users = User.query.filter(User.id.notin_((1, 3, 5))).all()
      
    • 内容

      # 包含指定内容
      # users = User.query.filter(User.email.contains('ng')).all()
      # 以指定内容开头
      # users = User.query.filter(User.email.startswith('fe')).all()
      # 以指定内容结尾
      # users = User.query.filter(User.email.endswith('.com')).all()
      # 模糊匹配
      # users = User.query.filter(User.email.like('l%')).all()
      users = User.query.filter(User.email.notlike('l%')).all()
      
    • 逻辑

      from sqlalchemy import and_, or_
      
      # 默认的关系就是逻辑与
      # users = User.query.filter(User.id > 3, User.age > 20).all()
      # 与上式等价
      # users = User.query.filter(and_(User.id > 3, User.age > 20)).all()
      # 逻辑或
      users = User.query.filter(or_(User.id > 3, User.age > 20)).all()
      

  • 相关阅读:
    python定时任务:apscheduler的使用(还有一个celery~)
    Python定时任务-schedule vs. Celery vs. APScheduler
    结合Django+celery二次开发定时周期任务
    The Django Book 2.0--中文版
    第十二章: 部署Django
    Django扩展自定义manage命令
    使用django-extension扩展django的manage――runscript命令
    Django | 执行项目下指定的脚本
    C语言宏定义技巧——多次包括头文件内容不同
    《Java并发编程实战》第十章 避免活跃性危急 读书笔记
  • 原文地址:https://www.cnblogs.com/swjblog/p/9741675.html
Copyright © 2011-2022 走看看