在认识Flask-SQLAlchemy之前,先要了解ORM和SQLAlchemy。
概念
ORM:对象关系映射,英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping)
产生背景:
面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系型数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。
具体表现:
表现为我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQL 语句打交道,只需简单的操作实体对象的属性和方法。ORM 技术是在对象和关系之间提供了一条桥梁,前台的对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化 。
缺点 :
1、相比较直接使用SQL语句操作数据库,有性能损失.
2、根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.
SQLAlchemy是Python一款非常强大的ORM软件。
SQLAlchemy是一个关系型数据库框架,它提供了高层的 ORM 和底层的原生数据库的操作,让开发者不用直接和 SQL 语句打交道,而是通过 Python 对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升。
Flask-SQLAlchemy是一个简化了 SQLAlchemy 操作的flask扩展
安装及配置:
pip install flask-sqlalchemy
数据库连接配置:
# 配置数据库的连接(以mysql为例)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:mysql@localhost/数据库名'
# 关闭动态追踪修改的警告信息
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 展示sql语句
#app.config['SQLALCHEMY_ECHO'] = True
其它配置:
SQLALCHEMY_POOL_SIZE 数据库连接池的大小。默认是引擎默认值(通常 是 5 )
SQLALCHEMY_POOL_TIMEOUT 设定连接池的连接超时时间。默认是 10 。
SQLALCHEMY_POOL_RECYCLE 多少秒后自动回收连接。这对MySQL是必要的,它默认移除闲置多于 8 小时的连接。注意如果使用了MySQL Flask-SQLALchemy 自动设定这个值为 2 小时。
创建数据库的表:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
#post表
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) # 发布博文的时间
body_html = db.Column(db.Text) # 存放转换后的 HTML 代码
author_id = db.Column(db.Integer, db.ForeignKey('users.id')) # 外键使用 ForeignKey,指向 User 表的 id
comments = db.relationship('Comment', backref='post', lazy='dynamic')
#权限表
class Permisson(db.Model):
__tablename__ = 'permission'
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64),unique =True,nullable=False) # 权限名称
abbreviation = db.Column(db.String(64), unique=True,nullable=False)
class User(db.Model):
__tablename__:'user'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String,nullable=False)
# 生成数据表
db.create_all()
增:向数据库中添加数据要通过模型类来添加
db.session.add(模型类类名) #添加一条数据
db.session.commit() #在添加完之后,要有提交和回滚
db.session.rollback()
#db.session.add_all([us1,us2,...]) 添加多条数据(列表的形式)
删:
author = Author.query.get(id) # 先找到要删除的数据
db.session.delete(author) # 执行删除
db.session.commit()
db.session.rollback()
改:
方法一:
user = User.query.first()
user.name = 'dong'
db.session.commit()
方法二:
User.query.filter(User.name=='zhang').update({'name':"li"})
db.session.commit()
查:
get查询: User.query.get(1) 参数为主键,如果主键存在,没有返回值。
过滤查询:
User.query.filter(User.name=='wang').first() 都是过滤查询,接收的参数必须使用模型类的类名,都必须使用查询执行器。
User.query.filter_by(name='wang').all() 只能使用等值操作,参数为具体模型类的字段名,使用查询执行器。
User.query.filter().all() filter查询不加条件,相当于查询所有数据。
User.query.filter().limit(2).all() 限制查询数据的条目数
分页查询:
paginate = User.query.filter().paginate(1,2,False)
返回的是paginate对象,第一个参数为当前页数,第二个参数为每页的数据,第三个参数为false分页错误不报错
paginate.page 获取当前页数
paginate.pages 获取总页数
paginate.items 获取当前页数所有数据
排序查询:
User.query.order_by(User.id.desc()).all() 降序排序
User.query.order_by(User.id.asc()).all() 升序排序
※ limit:限制数据条目数,count:计数
关联查询示例:
代码中的关系引用定义:
us = db.relationship('User',backref='role')
一对多查询:使用relationship返回的对象。
>>> r = Role.query.get(1)
# 查询管理员有多少人
>>> r.us
[name:wang, name:zhou]
多对一查询:使用反向引用;
>>> User.query.get(2)
name:zhang
>>> u = User.query.get(2)
# 查询zhang的角色是什么
>>> u.role
name:user
@app.route('/', methods=['GET', 'POST'])
def index():
form = NameForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.name.data).first()
if user is None:
user = User(username=form.name.data)
db.session.add(user)
session["known"] = False
else:
session["known"] = True
session["name"] = form.name.data
form.name.data = "" # why empty it ?
return redirect(url_for("index"))
return render_template("index.html", current_time=datetime.utcnow(), form=form,
name=session.get("name"), known=session.get("known"))
可查看:https://www.pyfdtic.com/2018/03/19/flaskExt--flask-sqlalchemy/