flask14-orm简介及数据库的基本操作
ORM 全拼Object-Relation Mapping.
中文意为 对象-关系映射.
主要实现模型对象到关系数据库数据的映射.
比如:把数据库表中每条记录映射为一个模型对象
ORM图解
优点 :
只需要面向对象编程, 不需要面向数据库编写代码.
对数据库的操作都转化成对类属性和方法的操作.
不用编写各种数据库的sql语句.
实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
不在关注用的是mysql、oracle...等.
通过简单的配置就可以轻松更换数据库, 而不需要修改代码.
缺点 :
相比较直接使用SQL语句操作数据库,有性能损失.
根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.
在 Flask-SQLAlchemy 中,数据库使用URL指定,而且程序使用的数据库必须保存到Flask配置对象的 SQLALCHEMY_DATABASE_URI 键中
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
其他设置:
# 动态追踪修改设置,如未设置只会提示警告
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True#查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True
其他配置
名字 |
备注 |
SQLALCHEMY_DATABASE_URI |
用于连接的数据库 URI 。例如:sqlite:////tmp/test.dbmysql://username:password@server/db |
SQLALCHEMY_BINDS |
一个映射 binds 到连接 URI 的字典。更多 binds 的信息见用 Binds 操作多个数据库。 |
SQLALCHEMY_ECHO |
如果设置为Ture, SQLAlchemy 会记录所有 发给 stderr 的语句,这对调试有用。(打印sql语句) |
SQLALCHEMY_RECORD_QUERIES |
可以用于显式地禁用或启用查询记录。查询记录 在调试或测试模式自动启用。更多信息见get_debug_queries()。 |
SQLALCHEMY_NATIVE_UNICODE |
可以用于显式禁用原生 unicode 支持。当使用 不合适的指定无编码的数据库默认值时,这对于 一些数据库适配器是必须的(比如 Ubuntu 上 某些版本的 PostgreSQL )。 |
SQLALCHEMY_POOL_SIZE |
数据库连接池的大小。默认是引擎默认值(通常 是 5 ) |
SQLALCHEMY_POOL_TIMEOUT |
设定连接池的连接超时时间。默认是 10 。 |
SQLALCHEMY_POOL_RECYCLE |
多少秒后自动回收连接。这对 MySQL 是必要的, 它默认移除闲置多于 8 小时的连接。注意如果 使用了 MySQL , Flask-SQLALchemy 自动设定 这个值为 2 小时。 |
完整连接 URI 列表请跳转到 SQLAlchemy 下面的文档 (Supported Databases) 。这里给出一些 常见的连接字符串。
Postgres: postgresql://scott:tiger@localhost/mydatabase
MySQL: mysql://scott:tiger@localhost/mydatabase
Oracle: oracle://scott:tiger@127.0.0.1:1521/sidname
SQLite (注意开头的四个斜线): sqlite:////absolute/path/to/foo.db
类型名 |
python中类型 |
说明 |
Integer |
int |
普通整数,一般是32位 |
SmallInteger |
int |
取值范围小的整数,一般是16位 |
BigInteger |
int或long |
不限制精度的整数 |
Float |
float |
浮点数 |
Numeric |
decimal.Decimal |
普通整数,一般是32位 |
String |
str |
变长字符串 |
Text |
str |
变长字符串,对较长或不限长度的字符串做了优化 |
Unicode |
unicode |
变长Unicode字符串 |
UnicodeText |
unicode |
变长Unicode字符串,对较长或不限长度的字符串做了优化 |
Boolean |
bool |
布尔值 |
Date |
datetime.date |
时间 |
Time |
datetime.datetime |
日期和时间 |
LargeBinary |
str |
二进制文件 |
选项名 |
说明 |
primary_key |
如果为True,代表表的主键 |
unique |
如果为True,代表这列不允许出现重复的值 |
index |
如果为True,为这列创建索引,提高查询效率 |
nullable |
如果为True,允许有空值,如果为False,不允许有空值 |
default |
为这列定义默认值 |
选项名 |
说明 |
backref |
在关系的另一模型中添加反向引用 |
primary join |
明确指定两个模型之间使用的联结条件 |
uselist |
如果为False,不使用列表,而使用标量值 |
order_by |
指定关系中记录的排序方式 |
secondary |
指定多对多关系中关系表的名字 |
secondary join |
在SQLAlchemy中无法自行决定时,指定多对多关系中的二级联结条件 |
makedata.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置数据库链接地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://user1:123456@127.0.0.1:3306/alchemy'
# 是否跟踪数据库的修改
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# 初始化数据库操作对象
db = SQLAlchemy(app)
@app.route('/', methods=['post'])
def index():
return '数据库链接'
# 角色
class Role(db.Model):
__tablename__ = "roles" # 指定表名,如果不指定会以类名的小写做为表名
# 定义主键 id,默认会自增长
id = db.Column(db.Integer, primary_key=True)
# 角色的称呼
name = db.Column(db.String(128), unique=True)
# 可以直接通过当前类的对象.users 就可以访问到当前角色对应的所有用户
# backref 反向引用,表示给其前面的类添加一个属性()
# 在此表示给 User 这个类添加 role 的属性,以便能够直接通过 user.role 访问到一的这一方的数据
# 定义 relationship 在一的这一方定义,第一个参数写多的这一方的类名,backref 写一的这一方的类名小写
# 如果指定lazy='dynamic',只有在真正使用 users的时候(.first(), 遍历)orm才会帮我们去查询数据
# backref=db.backref("role", lazy='dynamic'),
users = db.relationship("User", backref="role", lazy='dynamic')
# 用户
class User(db.Model):
__tablename__ = "users"
# 主键
id = db.Column(db.Integer, primary_key=True)
# 用户名
name = db.Column(db.String(128), unique=True)
# 邮箱
email = db.Column(db.String(128), unique=True)
# 用户密码
password = db.Column(db.String(128))
# 外键-关联roles
role_id = db.Column(db.INTEGER, db.ForeignKey('roles.id'))
def executive():
try:
db.drop_all() # 删除表
db.create_all() # 创建表
# 新增数据
ro1 = Role(name="admin")
ro2 = Role(name="user")
db.session.add_all([ro1, ro2])
db.session.commit()
# 修改数据
# ro1 = Role(name='admin')
# db.session.add(ro1)
# 再次插入一条数据
# ro2 = Role(name='user')
# db.session.add(ro2)
# 一次插入多条数据
us1 = User(name='wang', email='wang@163.com', password='123456', role_id=ro1.id)
us2 = User(name='zhang', email='zhang@189.com', password='201512', role_id=ro2.id)
us3 = User(name='chen', email='chen@126.com', password='987654', role_id=ro2.id)
us4 = User(name='zhou', email='zhou@163.com', password='456789', role_id=ro1.id)
us5 = User(name='tang', email='tang@itheima.com', password='158104', role_id=ro2.id)
us6 = User(name='wu', email='wu@gmail.com', password='5623514', role_id=ro2.id)
us7 = User(name='qian', email='qian@gmail.com', password='1543567', role_id=ro1.id)
us8 = User(name='liu', email='liu@itheima.com', password='867322', role_id=ro1.id)
us9 = User(name='li', email='li@163.com', password='4526342', role_id=ro2.id)
us10 = User(name='sun', email='sun@163.com', password='235523', role_id=ro2.id)
db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10])
# pass
except Exception as e:
print(e)
else:
db.session.commit()
def local_query():
try:
User.query.all()
except Exception as e:
print(e)
if __name__ == '__main__':
executive()
app.run(debug=True)
"""
查询所有用户数据
User.query.all()
查询有多少个用户
User.query.count()
查询第1个用户
User.query.first()
查询id为4的用户[3种方式]
User.query.get(4)
User.query.filter(User.id == 4).first()
User.query.filter_by(id=4).first()
查询名字结尾字符为g的所有数据[开始/包含]
User.query.filter(User.name.endswith('g')).all()
# 开始 startswith
# 包含 contains
查询名字不等于wang的所有数据[2种方式]
User.query.filter(User.name != 'wang').all()
from sqlalchemy import not_
User.query.filter(not_(User.name == 'wang')).all()
查询名字和邮箱都以 li 开头的所有数据[2种方式]
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.email.startswith('li'))).all()
查询password是 `123456` 或者 `email` 以 `itheima.com` 结尾的所有数据
User.query.filter(User.password == '123456', User.email.endswith('itheima.com')).all()
查询id为 [1, 3, 5, 7, 9] 的用户列表
User.query.filter(User.id.in_([1,3,5,7,9])).all()
查询name为liu的用户所对应的角色数据
role_id = User.query.filter(User.name == "liu").first().role_id
Role.query.get(role_id)
查询所有用户数据,并以email排序
# 默认是 asc() 顺序 倒序就是在属性后面调用 desc()
User.query.order_by(User.email.desc()).all()
每页3个,查询第2页的数据
# paginate 函数有三个参数,
第1个表示查询第几页数据
第2个表示每页多少个
第3个如果有错是否抛出错误
该函数的返回值是一个 paginate 对象
paginate = User.query.paginate(2, 3, False)
获取总页数
paginate.pages
获取当前页数
paginate.page
获取当前页数据
paginate.items
查询name 为 admin这个角色所有的用户
方式1:
role = Role.query.filter(Role.name == "admin").first()
User.query.filter(User.role_id == role.id).all()
方式2:
Role.query.filter(Role.name == "admin").first().users
得到第二个用户 / 第n个用户的信息
adminuser = Role.query.filter(Role.name == "admin").first().users
adminuser[1]/ adminuser[n-1]
查询 id 为 3 所对应的角色
方式1:
role_id = User.query.filter(User.id == 3).first().role_id
Role.query.get(role_id)
方式2:
User.query.filter(User.id == 3).first().role
方式3:
User.query.get(3).role
"""
pycharm中使用Terminal做查询操作