current_app

  1. '''
  2. current_app = LocalProxy(_find_app)
  3. request = LocalProxy(partial(_lookup_req_object, "request"))
  4. session = LocalProxy(partial(_lookup_req_object, "session"))
  5. g = LocalProxy(partial(_lookup_app_object, "g"))
  6. '''

代理的request这么一个类,在请求过程中
只要是访问路由,就可以通过current_app来获取到其他东西。
例如 current_app.config.
app同样可以获取到,为什么使用current_app.config?

是为了线程安全,通常一个app路由内只有一个请求。
current_app里面的属性是不会跑到别的app请求中去的,
但是在大型项目中,app逻辑代码并不是写在同一个模块下,在只想访问当前app路由的情况下使用current_app来调用,保证线程安全。

orm

什么是orm,关系映射,类似ssh中的数据层实现。
学习成本搞,但是性能比不上原生。
可以提高开发效率,应用元编程概念

sqlite

python自带sqlite3,小巧,且功能较为强大,百万计。
不需要联网,db信息保存在一个db格式的文件中,方便进行数据迁移。
多用于测试平台,单机小游戏。

编程模式上的区别

原生 sql ,谁都可以读懂,但是维护成本高,开发效率底
orm关系映射对象,层层封装,将简单的sql查询进行封装,
通过类,属性,方法的方式映射sql语句进行调用

好处
避免sql注入,各个不同的数据需要不同的查询sql,这个不用
坏处
每一个具体的语法是不一样的,sql语句大体通用,学习成本高。

使用流程

导包

  1. from flask_sqlalchemy import SQLAlchemy
  2. from flask_migrate import Migrate
  3. from flask import Flask
  4. # 初始化 db 数据库对象,吧app和db绑定到一起
  5. app = Flask(__name__)
  6. app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@localhost:3306/demo"
  7. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
  8. db uri地址构成
  9. mysql(db类型),pymysql(引擎)://root(用户名):密码@localhost3306/demo(db name)
  10. 使用sqlite 3个斜杠,linux下是 4个斜杠
  11. # --------- 一个项目使用多个数据库的情况下 ,绑定多个db
  12. app.config['SQLALCHEMY_BINDS']={
  13. 'users':"sqlite:///d:/demo1.db"
  14. }
  15. 模型类也要绑定
  16. class user(db.Model):
  17. __bind_key__ ="user"
  18. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
  19. db = SQLAlchemy(app)

绑定与延迟绑定

  1. app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@localhost:3306/demo"
  2. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
  3. db = SQLAlchemy(app)
  4. 延迟绑定
  5. db.init_app(app) # 初始化db绑定app,但是一定要再app路由生效之前,要注意代码执行顺序

编写数据库表类并构建DB

  1. class User(db.Model):
  2. __tablename__ = "user"
  3. id = db.Column(db.Integer, primary_key=True)
  4. username = db.Column(db.String(80), unique=True)
  5. email = db.Column(db.String(120), unique=True)
  6. ## 通过migrate 构建数据库
  7. # 1,迁移的时候更加方便
  8. # 2,可以动态修改db结构
  9. migrate = Migrate(app, db)

migrate 方式常用命令

初始化 flask db init

该命令会新建一个名字位migrations的文件夹,并记录一个数据库版本号
一份保留再migrations中,一份保存再数据库中(新建一张名字为alembic_version的表来保存
值得注意的是新建了migrations文件夹后需要对db模型进行修改,然后使用flask-migrations进行迁移,
这样才产生第一个版本号。

数据迁移 flask db migrate

迁移脚本最好仔细审查按需求编写

升级 flask db upgrade

每次db模型变化,需要重复使用migrate命令和upgrade命令,
按照顺序组合使用,成功后会修改版本号。

帮助

flask db —help

数据模型定义参数说明

  1. class User(db.Model):
  2. __tablename__="user"
  3. id = db.Column(db.Integer,primary_key=True)
  4. username = db.Column(db.String(80),unique=True)
  5. email = db.Column(db.String(120),unique=True)
  6. 属性
  7. db.Model 继承db下面的基类,与db进行绑定
  8. db.Column
  9. 最常的数据格式
  10. db.String 字符串需要指明长度
  11. db.Text 长的unicode文本
  12. DateTime 表示为python datetime 对象的时间和日企
  13. intger
  14. smallintger
  15. float
  16. Boolean 存储布尔值
  17. PickleType 存储为一个持久化的python对象
  18. LargeBinary 存储一个任意大的二进制数据
  19. 参数
  20. db.ForeginKey('project.id')
  21. primary.key 主键,唯一标示
  22. autoincrement 自增长
  23. unique 唯一
  24. index 索引可以极大的提高查询的速度,但是索引很多的话,查询速度会降低,且写入速度会降低
  25. nullable 不为空
  26. default 默认
  27. comment 说明,注释

简单操作

  1. @app.route("/")
  2. def index():
  3. new_user = User(username="addicated",email="demo")
  4. db.session.add(new_user)
  5. db.session.commit()
  6. return "hello"
  7. # 查询
  8. @app.route("/")
  9. def index():
  10. users = User.query.all()
  11. print(users)
  12. return "hello"
  13. user =User(username="demo")
  14. db.session.add(user)
  15. # 添加多个
  16. # db.session.add_all([user1,user2])

事务

与各种db处理逻辑一样,orm同样支持事务操作

  1. # 事务,一连串的数据库操作、
  2. # 加一个异常处理,如果报错了就rollback
  3. try:
  4. db.session.commit() # 只有在commit的时候才会生效到数据库中
  5. except:
  6. db.session.rollback()

Query对象

  1. # orm
  2. # 1,所有的all() 查询满足条件的所有字段
  3. # users= User.query.where().group_by().offset().all() # 支持链式调用
  4. users = User.query.all()
  5. # 基本原理是每个方法都返回一个统一的方法,之后就可以一直调用下去
  6. # 直到返回的不再是同一个对象或者方法
  7. # 2,first 拿到查询的第一个结果
  8. user = User.query.first()
  9. # 3,get方法 要通过主键去获取 主键唯一,是一个位置参数
  10. user = User.query.get(5) # 位置传参,不能
  11. # 表内有多个主键的情况下,使用元祖传入进去
  12. # 或者使用字典 kv方式传入进去
  13. # 如果没获取到,会返回一个None,获取到的话会返回一个模型
  14. # 如果没返回数据,想要其报错的话,
  15. Query.get_or_404()
  16. # 4,filter_by()
  17. # 第一种 使用filter_by方法
  18. Query.filter_by()
  19. # 5 filter() 进行更为复杂的查询
  20. Query.filter() # 位置传参
  21. User.query.filter(User.email.endswith("xxx")).all()
  22. # 支持字段很多,在ColumnOperators中进行确认
  23. ColumnOperators
  24. # 6 按照某种规则对用户进行排序
  25. User.query.order_by(User.username.desc().all())
  26. # 7 限制返回用户的数量,应用场景,进行分页
  27. User.query.order_by(User.username.desc()).limit(1).all()
  28. # 删除
  29. db.session.delete("")
  30. # 删除需要commit才能生效
  31. # first_or_404
  32. # 没有找到就abort() 和异常处理机制配合起来使用
  33. # 数据更新
  34. user = User()
  35. db.session.add(user)
  36. # 添加多个
  37. # db.session.add_all([user1,user2])
  38. db.session.ccommit()
  39. # orm 执行原生sql语句
  40. users = db.session.execute("select * from users")
  41. # 原生sql语句的参数化
  42. sql = "select * from user where name=:name"
  43. a = db.session.execute(sql, params={'name': "value"})
  44. print(a.fetchall())