Pyhton拓展数据库

611 阅读5分钟

1. ORM

  • ORM即对象-关系映射
  • 主要实现模型对象到关系数据库数据的映射

1.1 ORM图解

1.2 优点

  • 只需要面向对象编程,不需要面向数据库编写代码
    1. 对数据库的操作都转化成对类属性和方法的操作
    2. 不用编写各种数据库的SQL语句
  • 实现了数据模型与数据库的解耦,屏蔽了不同数据操作上的差异
    1. 不在关注用的是MySQL、oracle等
    2. 通过简单的配置就可以轻松更换数据库,而不需要修改代码

1.3 缺点

  • 相比直接使用SQL语句操作数据库有性能损失
  • 根据对象的操作转换成SQL语句,根据查询的结果转化成对象,在映射过程中有性能损失

2. Flask-SQLAlchemy

  • SQLALchemy实际上是对数据库的抽象,让开发者不用直接和SQL语句打交道,而是通过Python对象来操作数据库,舍弃了一些性能,换来开发效率提升
  • SQLalchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLalchemy操作的flask拓展。

2.1 数据库连接设置

# 需要创建数据库,使用其名
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://MySQL用户名:MySQL密码@127.0.0.1:3306/数据库名字'
# 动态追踪修改设置,如未设置只会提示警告
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
#查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True

2.2 常用的SQLAlchemy字段类型

类型名 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 二进制文件

2.3 常用的SQLAlchemy列选项

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

2.4 常用的SQLAlchemy关系选项

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

3. 数据库的基本操作

3.1 在视图函数中定义模型类

from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)

#设置连接数据库的URL
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
db = SQLAlchemy(app)

class Role(db.Model):
    # 定义表名
    __tablename__ = 'roles'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    us = db.relationship('User', backref='role')

    #repr()方法显示一个可读字符串
    def __repr__(self):
        return 'Role:%s'% self.name

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    email = db.Column(db.String(64),unique=True)
    password = db.Column(db.String(64))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    def __repr__(self):
        return 'User:%s'%self.name
if __name__ == '__main__':
    app.run(debug=True)

3.2 一对多的关联

class Role(db.Model):
    ...
    # 关键代码
    us = db.relationship("user",backref="role", lazy="danamic")
    
class User(db.Model):
    ...
    role_id = db.Column(db.Integer, db.ForeignKey("roles.id")
  • 其中realtionship描述了Role和User的关系,第一个参数为“1”的一方,可以直接查“1”后面对应的“多”的一方的信息
  • 第二个参数backref声明可以通过“多”的一方直接查询到“1”的一方的信息
  • 第三个参数为懒加载,决定了什么时候SQLALchemy从数据库中加载数据
# 查询roles表id为1的角色
ro1 = Role.query.get(1)
# 查询该角色的所有用户
ro1.us.all()

# 查询users表id为3的用户
us1 = User.query.get(3)
# 查询用户属于什么角色
us1.role

3.3 常用的SQLAlchemy查询过滤器

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

3.4 常用的SQLAlchemy查询执行器

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

3.4 相关命令

  • 创建表:db.create_all()
  • 删除表:db.drop_all()
  • 插入数据:db.session.add(变量)(需要commit提交才生效)
  • 返回查询到的第一个对象:对象名.query.first()
  • 返回查询到的所有对象:对象名.query.all()
  • filter模糊查询:对象名.query.filter(限制条件).first/all()
  • get查找:对象名.query.get()参数为主键,如果主键不存在没有返回内容
  • 逻辑非:!=或者not_(需要导包)
  • 逻辑与:and_(需要导包)
  • 逻辑或:or_(需要导包)