Flask——数据库简介

ORM

ORM:全拼 Object-Relation Mapping
中文名:对象关系映射
主要实现模型对象到关系数据库数据的映射,比如把数据库表每条记录映射为一个模型对象。但是数据库需要手动创建。
优点 :
只需要面向对象编程, 不需要面向数据库编写代码.
对数据库的操作都转化成对类属性和方法的操作.
不用编写各种数据库的sql语句.
实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
不在关注用的是mysql、oracle...等.
通过简单的配置就可以轻松更换数据库, 而不需要修改代码.
缺点 :
相比较直接使用SQL语句操作数据库,有性能损失.
根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.
SQLAlchemy:关系型数据库抽象框架,用来实现ORM
使用Flask-SQLAlchemy扩展包来具体实现SQLAlchemy。

Flask_SQLAlchemy的配置说明:

SQLALCEHMY_DATABASE_URI:用于连接数据库URI
SQLALCHEMY_BINDS:一个映射binds到URI的字典
SQLALCHEMY_ECHO:如果设置为True,SQLAlchemy会打印mysql语句
SQLALCHEMY_RECORD_QUERIES:可以显式的禁用或启用查询语句,查询语句在调式或者测试模式自动启用。
SQLALCEHMY_NATIVE_UNICODE:可以用于显式禁用原生unicode支持,当使用不合适的指定无编码的数据库默认值时,这对于一些数据库适配器是必须的
SQLALCEHMY_POOL_SIZE:数据库连接池的大小,默认是引擎的默认值,通常是5
SQLALCHEMY_POOL_TIMEOUT:设置连接池的连接超时时间,默认是10
SQLALCHEMY_POOL_RECYCLE:多少秒后自动收回连接,这对Mysql是必要的,它默认移除连接超过8小时的连接。注意如果使用了Mysql。Flask_SQLAlchemy自动设定这个值为2小时。

常用的SQLAlcehmy的字段类型

Integer	:普通整数,一般是32位
SmallInteger:		取值范围小的整数,一般是16位
BigInteger	:	不限制精度的整数
Float	:	浮点数
Numeric	:	普通整数,一般是32位
String	:变长字符串
Text	:	变长字符串,对较长或不限长度的字符串做了优化
Unicode	:变长Unicode字符串
UnicodeText	:	变长Unicode字符串,对较长或不限长度的字符串做了优化
Boolean	:	布尔值
Date	:	时间
Time	:日期和时间
LargeBinary	:	二进制文件

常用的SQLAlcehmy列选项:

primary_key:	如果为True,代表表的主键
unique:	如果为True,代表这列不允许出现重复的值
index:如果为True,为这列创建索引,提高查询效率
nullable:如果为True,允许有空值,如果为False,不允许有空值
default	:为这列定义默认值

常用的SQLAlcehmy的关系选项:

backref :在关系的另一模型中添加反向引用 
primary join: 明确指定两个模型之间使用的联结条件 
uselist: 如果为False,不使用列表,而使用标量值 
order_by: 指定关系中记录的排序方式 
secondary: 指定多对多关系中关系表的名字 
secondary join :在SQLAlchemy中无法自行决定时,指定多对多关系中的二级联结条件

代码

from flask import Flask
# 导入扩展包
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 数据库指定连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@localhost/homework'
#动态追踪修改,无论设置与否,不会影响代码的运行。只会提示警告信息。如果设置为True,会跟踪数据库的变化,会影响代码的效率,设置为False,不影响代码的效率。
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
#展示sql语句:会转换出mysql创建表操作的原理。
app.config['SQLALCHEMY_ECHO'] = True

# 使用sqlalchemy,需要实例化sqlalchemy,必需传入实例app,让策划嗯需实例app和sqlalchemy进行关联
db = SQLAlchemy(app)

"""
 需求:实现一对多模型类的定义和基本数据的增删改查
 Role(角色)一方,管理员和普通用户
 user(用户)多方,具体的用户
 实现流程:
 1.使用flask_sqlalchemy扩展包,配置数据库的连接
 2.定义模型类
"""

# 定义模型类,必须继承自db.Model
class Role(db.Model):
    # 数据库表名,可以不定义,会默认创建同类型的表名,即role。
    # 表名的常见定义样式:tb_roles;info_roles;
    __tablename__ = 'roles'
    #定义字段
    id = db.Column(db.Integer,primary_key=True)
    info = db.Column(db.String(32),unique=True)
    # 一方定义关系:第一个参数表示另外一方的类名,第二个参数backref表示的是反向引用
    # role可以让User对象使用,可以实现多对一的查询,例如:一个人是管理员还是普通用户?多对一查询
    # us可以让Role对象使用,实现一对多的查询,例如:管理员有多少人?一对多查询
    #关系引用在数据库中没有实体
    us = db.relationship('User',backref ='role')
    #定义__repr__方法:作用是返回一个对象的可读字符串
    def __repr__(self):
   		return  'info:%s' % self.info

    #定义用户模型类:注意外键(角色具体属于的身份信息)
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32))
    email = db.Column(db.String(32))
    pswd = db.Column(db.String(32))
    # 多方定义外键,指向一方表名的主键id
    role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
     #定义__repr__方法:
    def __repr__(self):
   		return  'name:%s' % self.name

 	
@app.route('/')
def index():
    return 'hello world'
	# db.session.rollback() 回滚
"""
Role.query.get(2) get查询接收的参数为主键,如果不存在,返回空

>>> User.query.filter() 返回的基础的查询对象
<flask_sqlalchemy.BaseQuery object at 0x10958fb00>

filter和filter_by查询:都是查询过滤器,要使用查询执行器;
User.query.filter(User.name=='wang').all() 参数:必须使用类名.字段,可以使用运算符>= == <= !=
使用filter居多,因为可以有更多的过滤。
补充:在使用或过滤的时候,需要from sqlalcehmy import or_  先导,不能直接使用。
User.query.filter_by(name='wang').all()参数:只需要使用字段名,不能使用运算符。

查询排序:
>>> User.query.filter().order_by(User.id.desc()).all() desc()表示降序排序
[name:zhou, name:chen, name:zhang, name:wang]
>>> User.query.filter().order_by(User.id.asc()).all() asc()表示升序排序
[name:wang, name:zhang, name:chen, name:zhou]

分页:第一个参数表示页数,第二个参数表示每页条目数,第三个参数分页异常不报错
>>> pa = User.query.filter().paginate(1,2,False)
>>> pa.items # 获取分页后的数据
[name:wang, name:zhang]
>>> pa.pages # 获取分页后的总页数
2
>>> pa.page # 获取当前页数
1
>>> pa = User.query.filter().paginate(2,2,False)
>>> pa.items
[name:chen, name:zhou]
>>> pa.pages
2
>>> pa.page
2

"""
if __name__ == '__main__':
    # 删除表
    db.drop_all()
    # 创建表
    db.create_all()
    #添加测试数据
    ro1 = Role(info='admin')
    ro2 = Role(info='user')
    # session表示数据库会话对象,add_all表示添加多条数据/add()
    # commit表示提交数据到数据库
    db.session.add_all([ro1, ro2])
    db.session.commit()
    us1 = User(name='wang', email='[email protected]', pswd='123456', role_id=ro1.id)
    us2 = User(name='zhang', email='[email protected]', pswd='201512', role_id=ro2.id)
    us3 = User(name='chen', email='[email protected]', pswd='987654', role_id=ro2.id)
    us4 = User(name='zhou', email='[email protected]', pswd='456789', role_id=ro1.id)
    db.session.add_all([us1, us2, us3, us4])
    db.session.commit()
	app.run(debug=True)

常用SQLAlchemy查询数据库:

filter(): 把过滤器添加到原查询上,返回一个新查询
filter_by(): 把等值过滤器添加到原查询上,返回一个新查询 limit 使用指定的值限定原查询返回的结果 
offset(): 偏移原查询返回的结果,返回一个新查询 
order_by(): 根据指定条件对原查询结果进行排序,返回一个新查询 
group_by(): 根据指定条件对原查询结果进行分组,返回一个新查询

常用SQLAlchemy查询数据库:

all()	以列表形式返回查询的所有结果
first()	返回查询的第一个结果,如果未查到,返回None
first_or_404()	返回查询的第一个结果,如果未查到,返回404
get()	返回指定主键对应的行,如不存在,返回None
get_or_404()	返回指定主键对应的行,如不存在,返回404
count()	返回查询结果的数量
paginate()	返回一个Paginate对象,它包含指定范围内的结果

数据库的查询操作:

first()返回查询到的第一个对象
all()返回查询到的所有对象
filter_by()精准查询
filter()模糊查询
get()参数为主键,如果主键不存在没有返回内容
not_相当于取反,但是and_,or_xu需要导入
查询数据后删除:需要先给查询后一个变量存储,然后db.session.delete(变量名),注意需要提交。
更新数据:和删除数据类似,然后修改提交。
关联查询:
查询角色的所有用户
**#查询roles表id为1的角色
ro1 = Role.query.get(1)
#查询该角色的所有用户
ro1.us.all()**
**查询用户所属角色
#查询users表id为3的用户
us1 = User.query.get(3)
#查询用户属于什么角色
us1.role**

猜你喜欢

转载自blog.csdn.net/weixin_43617255/article/details/83904405