ORM
一、概要
1、说明
ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法,
2、核心模块SQLAlchemy ORM 和SQLAlchemy Core
- Core是一种构建在表达式语言之上的一种API,一种SQL抽象工具包,允许用户以Python的语法格式构建SQL表达式,
- 而ORM 基于Core之上,一种更高级的、更加抽象的一种使用模式,其提供了现实业务对象与关系型数据库中表的一种关联关系,并实现两者之间的轻松转换
3、ORM优缺点
-
优点
1、隐藏了数据访问细节,封闭的通用数据库交互,ORM的核心,它使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
2、ORM使我们构造固化数据结构变得简单易行。
-
缺点
1、无可避免,自动化意味着映射和关联管理,代价是牺牲性能
##二、前期准备工作
1、安装插件
-
安装flask-sqlalchemy
pip install flask-sqlalchemy
-
安装Flask-Migrate
pip3 install Flask-Migrate
2、数据库设置
-
配置连接地址
#mysql mysql+pymysql://user:password@ip:port/db_name #oracle oracle+cx_oracle://user:password@ip:port/db_name
-
实例化SQLAlchemy
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
-
注册
# 需要Flask对象 db.init_app(app)
-
设置加载的url
app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://root:root@127.0.0.1:3306/flask'
-
配置migrate
# 实例化Migrate migrate = Migrate() migrate.init_app(app=app, db=db) # 添加命令脚本 from flask_migrate import MigrateCommand manager.add_command('db', MigrateCommand)
三、使用
1、定义模型
-
说明
模型表示程序中使用的持久化实体,在ORM中,模型是一个类,类中的属性对应数据库表中的列,类名对应数据库中的表名
持久化:是将程序数据在持久状态和瞬时状态间转换的机制。通俗的讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)
-
新建models.py文件
class User(db.Model): uid = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), index=True, unique=True, nullable=False) email = db.Column(db.String(100), index=True, unique=True) phone = db.Column(db.String(length=11), index=True, unique=True) age = db.Column(db.Integer, index=True, unique=True)
2、列类型对应的Python类型
-
类型
类型名 Python类型 说 明 Integer int 普通整数,一般是32位(常用) SmallInteger int 取值范围小的整数,一般是16位 BigInteger int或long 不限制精度的整数 Float float 浮点数 Numeric decimal.Decimal 定点数 String str 变长字符串(常用) Text str 变长字符串,对较长或不限长度的字符串做了优化(常用) Unicode unicode 变长Unicode字符串 UnicodeText Unicode 变长Unicode字符串,对较长或不限长度的字符串做了优化 Boolean bool 布尔值 Date datetime.date 日期 Time datetime.time 时间 DateTime datetime.datetime 日期和时间(常用) Interval datetime.timedelta 时间间隔 Enum str 一组字符串 PickleType 任何Python对象 自动使用pickle序列化 LargeBinary str 二进制文件 -
选项
选项名 说明 primary_key 如果设为True,这列就是表的主键 unique 如果设为True,这列不允许出现重复的值 index 如果设为True,为这列创建索引,提升查询效率 nullable 如果设为True,这列允许使用空值,如果设为False,这列不允许使用空值 default 为这列设定默认值 -
定义关系类型常用
选项名 说明 backref 在关系的另一个模型中添加反向引用 primaryjoin 明确指定两个模型之间使用的联结条件,只在模棱两可的关系中需要指定 lazy 指定如何加载相关记录,可选值有select(首次访问时按需加载)、immediate(源对象加载后就加载)、joined(加载记录,但使用联结)、subquery(立即加载,但使用子查询)、noload(永不加载)和dynamic(不加载记录,但提供加载记录的查询) uselist 如果设为False,不使用列表,而使用标量值 order_by 指定关系中记录的排序方式 secondary 指定多对多关系中关系表的名字 secondaryjoin SQLAlchemy无法自行决定时,指定多对多关系中的二级联结条件
3、添加数据
-
添加单个对象
@user.route('/add/', methods=['post', 'get']) def add(): if request.method == 'GET': return render_template('user/add.html') else: username = request.form.get('username') email = request.form.get('email') phone = request.form.get('phone') user = User(username=username, email=email, phone=phone) db.session.add(user) db.session.commit() users = User.query.all() return render_template('user/users.html', users=users)
-
添加多个对象
@user.route('/add/', methods=['post', 'get']) def add(): if request.method == 'GET': return render_template('user/add.html') else: db.session.add_all([User(username='test1', email='123@163.com', phone=12345678936), User(username='test2', email='1234@163.com', phone=123456789326)]) #提交 db.session.commit() return '添加多个对象'
4、更新数据
-
更新单个对象
@user.route('/update/<int:uid>/<username>/') def update(uid,username): user = User.query.filter_by(username=username).first() if user: user.email = '12345@example.com' db.session.commit() # 或者 user = User.query.get(uid) if user: user.username = '小明' db.session.commit() #或者 user = User.query.filter_by(uid=uid).update({"username": "hehe"}) db.session.commit() return '更新单个对象'
-
批量更新
# synchronize_session设置为False即执行字符串拼接 User.query.filter(User.like('_e%')).update({User.name: User.name + "test"}, synchronize_session=False) # synchronize_session设置为evaluate即执行四则运算 User.query.filter(User.id > 0).update({"age": User.age + 1}, synchronize_session="evaluate")
5、删除数据
-
操作步骤
@user.route('/del/<int:uid>/') def delete(uid): user = User.query.get(uid) if user: db.session.delete(user) db.session.commit() return redirect('user/show/')
6、查询数据
-
查询过滤器
过滤器 说明 filter() 条件过滤,把过滤器添加到原查询,返回新查询 filter_by() 把等值过滤器添加到原查询,返回新查询 limit() 使用指定值限制原查询返回的结果数量,返回新查询 offset() 偏移原查询返回的结果,返回新查询 order_by() 排序返回结果,返回新查询 groupby() 原查询分组,返回新查询 说明
这些过滤器返回的结果都是一个新查询,我的理解是这些查询其实是生成的SQL语句,
lazy
的惰性求值方式也体现在查询上,而这些语句不能生成需要查询的对象,需要调用其他的方法生成对象。
-
SQL查询执行函数
方法 说明 all() 以列表形式返回结果 first() 返回第一个结果,如果没有返回None first_or_404() 返回第一个结果,如果没有抛出404异常 get() 返回主键对应记录,没有则返回None get_or_404() 返回主键对应记录,如果没有抛出404异常 count() 返回查询结果数量 paginate() 返回paginate对象,此对象用于分页 -
操作符号
-
equals
query.filter(User.name == '小明')
-
not equals:
query.filter(User.name != '小明')
-
LIKE:
query.filter(User.name.like('%小%'))
-
IN
query.filter(User.name.in_(['小明', '小红', '小花'])) query.filter(User.name.in_( db.session.query(User.name).filter(User.name.like('%小%')) ))
-
NOT IN:
query.filter(~User.name.in_(['小明', '小红', '小花']))
-
IS NULL:
query.filter(User.name == None) query.filter(User.name.is_(None))
-
IS NOT NULL
query.filter(User.name != None) query.filter(User.name.isnot(None))
- AND
query.filter(and_(User.name == '小明', User.age == 18))
- OR
query.filter(or_(User.name == '小明', User.name == '小花'))
-