一、模型model
1、 什么是模型
模型 - 根据数据库中表结构而创建出来的class
数据库中每一张表对应到变成语言中就是一个class
表中的每一个列, 对应到变成语言中就是class的一个属性
2、模型的框架–ORM框架
1) 、 什么是ORM
ORM---Object Relational Mapping ,简称: ORM 、 O/RM 、 O/R Mapping
中文名: 对象关系映射
2) ORM的三大特征
- 数据表(Table) 到编程类(Class)的映射
- 数据类型的映射
数据库中表的字段以及数据类型对应到编程语言中就是类的属性及数据类型
- 关系映射( ******)
将数据库中表与表的关系对应到变成语言中类与类的关系
【1-1关系】:
A表中的一条数据只能与B表中的一条数据关联 ------ A表中的一条数据只能与B表中的一条数据关联
【1-多关系】
A表中的一条数据与B表中的多条数据关联 ------ A表中的一条数据只能与B表中的一条数据关联
【多-多关系】
A表中的一条数据与B表中的多条数据关联 ------ A表中的一条数据与B表中的多条数据关联
3) ORM的优点
- 封装了数据库中所有的操作,提升效率
- 可以省略庞大的数据访问层,即便不用SQL编码也能完成对数据库的CRUD操作
Create、Retrieve、Update、Delete
二、Flask中ORM框架
1、SQLALchemy 框架
1) 安装SQLALchemy : pip安装
2) Flask需要使用flask-sqlachemy支持包: pip install flask-sqlalchemy
2、在Flask中配置数据库
# app.config['SQLALCHEMY_DATABASE__URL'] = "mysql://用户名:密码@数据库服务地址:端口号/数据库"
app.config['SQLALCHEMY_DATABASE__URL'] = "mysql://root:123456@localhost:3306/flask"
# 创建SQLALchemy 的实例 -db,以后再程序中通过db来操作数据库
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
3、 拓展
统一资源标识符(Uniform Resource Identifier) ---URL
统一资源标识符(Uniform Resource Identifier) ---URL
create database flask default utf8 collate utf8_general_ci # 创建数据库
--- Navicat for Mysql 数据库第三方可视化工具
--- Power Designer 数据库建模工具
二、ORM框架熟知+数据库表设计 *****
1、创建模型model
1) Flask-SQLALchemy连接数据库以及创建表
flask应用实例
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['DEBUG'] = True
app.config["ENV"] = "development"
app.config['SQLALCHEMY_DATABASE_URL'] = "mysql://root:123456@localhost:3306/flask"
app.config['SQLALCHEMY_TRACE_MODIFICATIONS'] = False
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
class Role(db.Model):
__tablename = "my_users"
user_id = db.Column(db.Integer, primary_key=True)
user_name = db.Column(db.String(10), nullable=False)
@app.route("/index", endpoint="home")
def index():
return "这是首页"
if __name__ == "__name__":
db.create_all()
app.run(debug=True)
创建模型model-数据库配置
名称 说明
SQLALCHEMY_DATABASE_URL 用于链接的数据库URL:"mysql://用户名:密码@数据库服务地址:端口号/数据库"
SQLALCHEMY_BINDS 一个映射binds到链接URL的字典, 更多binds的信息见Binds操作多个数据库 ---- 连接多个数据库
SQLALCHEMY_ECHO 如果设置为True,SQLALchemy会记录所有发给stderr的语句,这对调试有用(打印sql语句)
SQLALCHEMY_RECORD_QUERIES 可以用于显式的禁用或启用查询记录。查询记录在调试或测试模式自动启用
SQLALCHEMY_NATIVE_UNICODE 可以用于显式禁用原生unicode支持。当使用不合适的指定无编码的数据库默认值时, 这对于
一些数据库适配器时必须的
SQLALCHEMY_POOL_SIZE 数据库链接池的大小。默认时引擎默认值(通常是5)
SQLALCHEMY_POOL_TIMEOUT 设定链接池的连接超时时间,默认是10
SQLALCHEMY_POOL_RECYCLE 多少秒自动回连连接。对MYsql是必要的。它默认移除闲置多余8小时的连接,注意如果使用了
MYSQL, Flask-SQLALchemy自动设定这个值为2小时
创建模型model-Binds操作多个数据库
示例配置–连接多个数据库
– 创建模型model-binds
SQLALCHEMY_DATABASE_URL = "mysql://root:123456@localhost:3306/flask"
SQLALCHEMY_BINDS = {
"users_1": SQLALCHEMY_DATABASE_URL,
"users_2": "mysql://root:123456@localhost:3306/flask2" }
– 创建和删除表
create_all() 和drop_all()方法默认作用域声明的所有bind,包括默认的, ,"__all__"可以指向一个bind名,或者所有binds,默认是:
bind(SQLALCHEMY_DATABASE_URL) 名为None:
dp。create_all()
dp.create_all(bind=['users_1'])
dp.drop_all(bind=['users_1'])
– 引用Binds
- 当声明模型时,可以用: __bin_key__属性指定bind
class Role(db.Model):
__bind_key__ = "users_1"
user_id = db.Column(db.Integer, primary_key=True)
- bind_key内部存储在表的info字典中,作为bind_key键值,:想要创建一个表对象时,可以如下
user_favorites = db.Table('user_favorites',
db.Column('user_id', db.Integer, db.ForeignKey('user_id')),
db.Column('message_id', db.Integer, db.ForeignKey('message_id')),
info={'bind_key', 'users_1'})
# 如果在模型上指定了__bind_key__, 你可以用他们准确的做想做的,模型会自行连接到指定的数据库连接
– 总结
binds? ----可以执行SQL语句并且通常是一个连接或引擎,,在Flask-SQLALchemy中,bind总是背后自动创建好引擎,引擎中的每个之后都会关联
短键(bind_key),这个键会在模型声明时使用,来把一个模型关联到一个特定引擎----若没有为模型指定bind key,会默认连接:
SQLALCHEMY_DATABASE_URL配置的值
2、 创建模型model—字段类型
1) 常见的SQLALchemy字段类型
类型名 Python类型 说明
Integer int 普通整数,一般32位
SmallInteger int 取值范围小的整数,一般16位
BigInteger int/long 不限精度的整数
Float float 浮点数
Numeric decimal.Decimal 普通整数,一般32位
String str 变长字符串
Text str 变长字符串,对较长或不限长度的字符串做了优化
Unicode unicode
Unicode Text unicode
Boolean bool 布尔
Date datetime.data 时间
Time datetime.datetime 日期和时间
LargeBinary str 二进制文件
2) 常用的SQLALchemy列选项
列选项 说明
primary_key 如果为True,代表表的主键
unique 如果为True,代表这列不允许出现重复值
index 如果为True,为这列创建索引,提高查询效率
nullable 如果为True,允许有空值,如果为False,不允许有空值
default 为这列定义默认值
3、 模型关系映射(一对一)
- 一对一在数据库中的设置
关联两张表中的任意一张表: 1) 增量外键,引用另一张表主键 2) 并且要实时唯一约束
- 在ORM中实现
1) 在任意一张表中增加外键和唯一约束
外键列名 = db.Column(db.Integer, db.ForeignKey(主表.主键),unique=True)
2) 在另一个实体类中增加关联属性和反向引用关系属性
属性名 = db.relationship('关联的实体类名',backref='反向引用关系属性名',uselist=False)
uselist: 设置为False, 表示关联属性是一个标量而非一个列表
- 示例
```
class Strudent(db.Model):
__tablename__ = "tb_student"
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
name = db.Column(db.String(250), comment="姓名")
age = db.Column(db.Integer, comment="年龄")
# 关联属性,是SQLALchemy提供给开发者快速引用外键模型的一个对象属性,不存在mysql中
# backref反向引用,类似django的related,通过外键模型查询主模型数据时的惯量属性
info = db.relationship('StrudentInfo', backref='own', uselist=False)
def __repr__(self):
return self.name
class StudentInfo(db.Model):
__tablename__ = "tb_student_info"
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
# 外键 -在另一模型中添加外键
sid = db.Column(db.Integer, db.ForeignKey(Strudent.id), comment="学生ID")
address = db.Column(db.String(250), nullable=True, comment="家庭住址")
mobile = db.Column(db.String(15), unique=True, comment="联系电话")
def __repr__(self):
return self.own.name
class Config:
DENUG = True
JSON_AS_ASCII = False
SQLALCHEMY_DATABASE_URL = "mysql://root:123456@localhost:3306/flask"
SQLALCHEMY_TRACK_MODIFICATIONS = True
SQLALCHEMY_ECHO = True
if __name__ == "__name__":
# 创建当前应用中声明的所有模型类对应的数据表,db.drop_all()是删除表
app.config.from_object(Config)
db = SQLAlchemy(app)
db.init_app(app) --- 初始化
```
4、 模型关系映射(一对多)
原则
在“多”的实体中增加外键关系
在“一”的试题中增加关联属性和反向引用关系属性
在 “多” 的实体中
外键列名 = db.Co(db.Integer, db.ForeignKey(‘主表.主键‘)
属性名=db.relationhip('多的实体类名',backref='反向引用的关系属性名',lazy='dynamic')
在“一”的实体中
增加关联属性和反向引用关系属性
属性名= db.relationship('多的实体类名',backref='反向引用关系属性名',lazy=dynamic)
lazy --- 指定如何加载相关记录
select : 首次访问时加载相关关联数据
immediate --- 元对象加载后立马加载关联数据(使用连接)
subquery --- 效果同上,使用子查询
noload --- 永不加载
dynamic ---- 不加载记录, 但提供加载记录的查询
如: Course与Teacher是存在一对多的关系
course = Course.query.filter_by(id=1).first
course.teachers.all()\course.teachers.first(),course.filter_by().all()
获取数据
- 通过“一”对象找“多” 的关联对象们
course = Course.query.filter_by(id=1).first()
teachers = course.teachers.all()
- 通过’多‘对象找’一‘的关联对象(通过反向引用关系属性 查找)
tea= Teacher.query.filter_by(id=1).first()
course = tea.course
5、 模型关系映射(多对多)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['DEBUG'] = True
app.config["ENV"] = "development"
SQLALCHEMY_DATABASE_URL = "mysql://root:123456@localhost:3306/flask"
app.config['SQLALCHEMY_DATABASE_URL'] = SQLALCHEMY_DATABASE_URL
db = SQLAlchemy(app)
""" 以db.Table关系表来确定模型之间的多对多关联"""
achievement = db.Table(
'tb_achievement',
db.Column('student_id', db.Integer, db.ForeignKey('tb_student.id')),
db.Column('course_id', db.Integer, db.ForeignKey('tb_course.id')),
db.Column('score', db.DECIMAL(5, 2), comment='成绩'),
db.Column('create_time', db.DateTime, comment='考试时间')
)
class Strudent(db.Model):
__tablename__ = "tb_student"
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
name = db.Column(db.String(250), comment="姓名")
age = db.Column(db.Integer, comment="年龄")
info = db.relationship('StrudentInfo', backref='own', uselist=False)
def __repr__(self):
return self.name
class Teacher(db.Model):
__tablename__ = "tb_teacher"
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
name = db.Column(db.String(250), comment="姓名")
sex = db.Column(db.Boolean, default=False, comment="性别")
age = db.Column(db.Integer, comment="年龄")
option = db.Column(db.Enum('老师', '助教', '班主任'), default='老师', comment='教职')
course_list = db.relationship('Course', uselist=True, backref='teacher', lazy='subquery')
def __repr__(self):
return self.name
class Course(db.Model):
__tablename__ = "tb_course"
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
name = db.Column(db.String(250), unique=True, comment="课程名称")
price = db.Column(db.Numeric(6, 2))
teacher_id = db.Column(db.Integer, db.ForeignKey(Teacher.id), comment="教职人员id")
student_list = db.relationship('Strudent', secondary=achievement, backref='course_list', lazy='dynamic')
def __repr__(self):
return self.own.name
class Config:
DENUG = True
JSON_AS_ASCII = False
SQLALCHEMY_DATABASE_URL = "mysql://root:123456@localhost:3306/flask"
SQLALCHEMY_TRACK_MODIFICATIONS = True
SQLALCHEMY_ECHO = True
if __name__ == "__name__":
app.config.from_object(Config)
db = SQLAlchemy(app)
db.init_app(app)
|