1.1 configuration and connection
- sqlalchemy python most powerful ORM framework
- flask-sqlalchemy flask component that allows flask can access sqlalchemy
- 安装 pip install flask-sqlalchemy
- Configuration
- SQLALCHEMY_DATABASE_URI: Database Connection Address
- SQLALCHEMY_TRACK_MODIFICATIONS: whether to modify the tracking database, after opening affect performance
- SQLALCHEMY_ECHO: When turned on, you can print sql language underlying execution in the console
- Mapping model class
- Class ---> table
- Class attribute ---> field
- Object ---> Record
- use
- Objects created app
- Create a database connection object objects by app
- Establish a mapping model
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置数据库的连接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test'
# 配置是否监听数据库变化, 性能较差, 不属于sqlalchemy本体
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 一旦开启, 可以显示底层执行的SQL语句
app.config['SQLALCHEMY_ECHO'] = True
# 创建数据库连接
db = SQLAlchemy(app)
# ORM 类->表 类属性->字段 对象->记录
class User(db.Model):
__tablename__ = 't_user' # 设置表明 默认为类名小写
id = db.Column(db.Integer, primary_key=True) # 主键 默认自增
name = db.Column(db.String(20), unique=True, index=True) # 设置唯一索引, 设置普通索引
email = db.Column(db.String(128), unique=True)
@app.route('/')
def index():
return 'index'
if __name__ == '__main__':
db.drop_all()
db.create_all()
app.run(debug=True, host='0.0.0.0')
1.2 increase data
- Create data objects
- Added to the session (converted to the corresponding sql statement)
- Submit session (this time will commit the transaction, the transaction commit fails, it will automatically rollback)
@app.route('/')
def index():
"""增加数据"""
# 1. 创建数据对象
user1 = User(name='zs', age=20)
# user1.name = 'zs'
# user1.age = 20
# 2. 添加到会话中 (转为对应的sql语句)
db.session.add(user1)
# 添加多个数据
# db.session.add_all([user1, user2, user3])
# sqlalchemy会自动创建隐式的事务, 并将sql操作添加到事务中
# 3. 提交会话, 此时就会提交事务, 事务提交失败, 会自动回滚
db.session.commit()
return 'index'
1.3 Data Query
- Discover all user data
User.query.all() # 返回的是列表, 里边包含的是模型对象
- Discover how many users
User.query.count()
- The first user query
User.query.first() # 返回模型对象
- 4 to query a user id [3 ways]
User.query.get(4) # 根据id查询
User.qeury.filter_by(id=4).all() # 简单查询器, 通过关键字实参来匹配字段,
# 返回BaseQuery对象, 可以续接更复杂的查询条件 all/count/first User.query.filter(User.id==4).first() # 复杂查询器 参数为恒等式/函数 返回BaseQuery对象
- Query name ending characters for all users g of [start / include]
User.query.filter(User.name.endswith('g')).all() # 名字以g结尾
User.query.filter(User.name.startwith('w')).all() # 名字以w开头
User.query.filter(User.name.contains('n')).all() # 名字包含n
User.query.filter(User.name.like('w%n%g')).all() # 模糊查询
- All user queries name and email are beginning to li [2 ways]
User.query.filter(User.name.startswith('li'), User.email.startswith('li')).all()
from sqlalchemy import and_
User.query.filter(and_(User.name.startswith('li'), User.emailstartswith('li'))).all()
- Queries are age 25 or 'email' all users 'itheima.com' ending
from sqlalchemy import or_
User.query.filter(or_(User.age==25, User.email.endswith('itheima.com'))).all()
- All user queries the name does not mean wang of [two ways]
from sqlalchemy import not_
User.query.filter(not_(User.name=='wang'))).all() User.query.filter(User.name != 'wang')).all()
- Id of the query [1, 3, 5, 7, 9] the user
User.query.filter(User.id.in_([1,3,5,7,9])).all()
- All users press the ages from small to large, then id descending order, take the first five
User.query.order_by(User.age, User.id.desc())).limit(5).all()
- Queries ages from small to large data bits 2-5
User.query.order_by(User.age).offset(1).limit(4).all()
- Data paging query, page 3, page 2 queries
pn = User.qeury.paginate(2, 3)
pn.items # 该页的数据
pn.pages # 总页数
pn.page # 当前页码
- The number of queries each age
from sqlalchemy import func
db.session.query(User.age, func.count(User.name)).group_by(User.age).all()
- Only queries lives and mailbox owner, optimizing queries (two ways) is used by default select *
users = User.query.options(load_only(User.name, User.email)).all() data = db.session.query(User.name, User.email).all()
1.3.1 slow query analysis
# 在mysql的配置文件 /etc/mysql/mysql.conf.d/mysql.cnf[mysqld]中配置懒查询
slow_query_log = ON # 是否已经开启慢查询
long_query_time = 1 # 慢查询统计标准, 超过1秒
slow_query_log_file = /usr/local/mysql/data/zzz-slow.log # 慢查询日志文件路径 log_queries_not_using_indexes = 1 # 如果值设置为ON, 则会记录所有利用索引的查询,性能优化时开启此项, 平时不要开启
# 重启mysql sudo /etc/init.d/mysql restart
# 查看懒查询启动情况 show variables like '%slow%'; show varibales like '%long_query_time%';
# 懒查询分析工具
mysqldumpslow
# -s: 排序方式 c 查询次数 t 查询时间 l 等待锁的时间 r 返回的记录数 at 平均查询时间
# -t: 返回前面多少条的数据;
# -g: 包含什么, 大小写不敏感的;
# 返回记录中查询次数最多的10个语句
sudo mysqldumpslow -s c -t 10 /usr/local/mysql/data/zzz-slow.log
# 返回记录中含有'user', 并且按照平均时间排序最慢的前10条语句
sudo mysqldumpslow -s at -t 10 -g 'user' /usr/local/mysql/data/zzz-slow.log
1.4 update, and delete
- Modify name = 'zs' user name 'lisi'
# 先查询, 后修改
user_obj = User.query.filter_by(name='zs').first()
user_obj.name = 'lisi'
# 使用update的子查询, update t_user set name='lisi' where name='zs';
User.query.filter_by(name='zs').update({'name':'lisi'})
db.session.commit() # 提交会话
- Delete name = 'zs' users
user_obj = User.query.filter_by(name='zs').first()
db.session.delete(user_obj) # delete的子查询
User.query.filter_by(name='zs').delete()
db.session.commit()
1.5 Pipeline
# sqlalchemy对mysql进行了优化, 实现了类似redis管道的机制, 如果会话中没有要执行查询
# (包含更新/删除的子查)和主动flush, 则所有的sql操作会在commit时才一起发送给mysql服务器
# 添加数据
user1 = User(name='zs', age=20)
db.session.add(user1)
# User.query.all() # 会将当前会话中的所有sql立即发送给mysql服务器
# db.session.flush() # 会将当前会话中的所有sql立即发送给mysql服务器
db.session.commit()