sqlalchemy 是python开发的一个ORM(数据库映射)模块: 将python面向对象的类映射为数据库的表,通过映射关系来完成数据库的操作,降低数据库操作的难度和繁琐程度。类似的模块还有(peewee)。
Flask将sqlalchemy进行封装,封装到自己的项目当中, sqlalchemy和flask-sqlalchemy的操作有一部分不同。
1、安装flask-sqlalchemy
pip install flask-sqlalchemy
SQLALCHEMY_DATABASE_URI flask_sqlalchemy 配置数据连接的参数
不同数据库连接方式不同:
Mysql mysql://username:password@hostname[:port]/database
Sqlite(windows) sqlite:///d:/python/python.sqlite
Sqlite(linux) sqlite:python/python.sqlite
Pgsql: postgresql://username:password@hostname/database
SQLALCHEMY_COMMIT_ON_TEARDOWN 请求结束后自动提交数据库修改
SQLALCHEMY_TRACK_MODIFICATIONS 如果设置成 True (默认情况),Flask-SQLAlchemy
将会追踪对象的修改并且发送信号。这需要额外的内存,如果不必要的可以禁用它。
flask_sqlalchemy的官方配置文档
3、flask-sqlalchemy简单使用实例
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy # 导入flask_sqlalchemy中的SQLAlchemy
# 创建flask实例
app = Flask(__name__)
# 当前文件绝对路径,用于拼接sqlite数据库生成文件
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
#app.config返回类字典对象,里面用来存放当前app实例的配置
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///"+os.path.join(BASE_DIR,"Demo.sqlite")
app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
#关联sqlalchemy和flask应用
db = SQLAlchemy(app)
class Student(db.Model):
__tablename__ = "students" #表名
id = db.Column(db.Integer,primary_key = True) #字段
name = db.Column(db.String(32),unique = True)
models.create_all() # 创建数据表
4、flask-sqlalchemy的表字段及参数说明
创建数据表
定义类,类下需要__tablename__来定义表的名称
字段类型
Integer int 普通整数,一般是 32 位
SmallInteger int 取值范围小的整数,一般是 16 位
Big Integer 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 主键
unique 不重复
index 索引
nullable 如果为True是可以为空
default 默认值
autoincrement 自增长
1、一对一关系
在一个表里记录另一个表的字段
2、一对多关系
使用字段类型db.Foreignkey("主键表.id")
# 关联sqlalchemy和flask应用
db = SQLAlchemy(app)
class Student(db.Model):
"""
学生表
"""
__tablename__ = "student"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(32))
age = db.Column(db.Integer)
gender = db.Column(db.Integer) # 1 男 0 女 -1 unknown
class Course(db.Model):
"""
课程表
"""
__tablename__ = "course"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(32))
description = db.Column(db.Text)
# 学生课程关联表(多对多),也可以使用下面的方式创建该表
Student_Course = db.Table(
"student_course",
db.Column("id",db.Integer,primary_key=True,autoincrement=True),
db.Column("student_id",db.Integer,db.ForeignKey("student.id")),
db.Column("course_id",db.Integer,db.ForeignKey("course.id")),
db.Column("delete_flag",db.Integer,default=1) # 1没有停课 0停课
)
# class Stu_Cou(db.Model):
# """
# 课程,学员关联表
# """
# __tablename__ = "student_course"
# id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# course_id = db.Column(db.Integer,db.ForeignKey("course.id"))
# student_id = db.Column(db.Integer, db.ForeignKey("student.id"))
搭建一个学生管理系统模型:
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
# app.config返回类字典对象,里面用来存放当前app实例的配置
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///"+os.path.join(BASE_DIR,"Student.sqlite")
app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
# 关联sqlalchemy和flask应用
db = SQLAlchemy(app)
class Student(db.Model):
"""
学生表
"""
__tablename__ = "student"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(32))
age = db.Column(db.Integer)
gender = db.Column(db.Integer) # 1 男 0 女 -1 unknown
class Course(db.Model):
"""
课程表
"""
__tablename__ = "course"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(32))
description = db.Column(db.Text)
# 学生课程关联表(多对多),也可以使用上面的方式创建该表
Student_Course = db.Table(
"student_course",
db.Column("id",db.Integer,primary_key=True,autoincrement=True),
db.Column("student_id",db.Integer,db.ForeignKey("student.id")),
db.Column("course_id",db.Integer,db.ForeignKey("course.id")),
db.Column("delete_flag",db.Integer,default=1) # 1没有停课 0停课
)
# class Stu_Cou(db.Model):
# """
# 课程,学员关联表
# """
# __tablename__ = "student_course"
# id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# course_id = db.Column(db.Integer,db.ForeignKey("course.id"))
# student_id = db.Column(db.Integer, db.ForeignKey("student.id"))
class Grade(db.Model):
"""
成绩表
学生、课程关联此表
"""
__tablename__ = "grade"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
grade = db.Column(db.Float,default=0)
student_id = db.Column(db.Integer,db.ForeignKey("student.id"))
course_id = db.Column(db.Integer,db.ForeignKey("course.id"))
class Attend(db.Model):
"""
考勤表:记录学生出勤状况
学生考勤:一对多
"""
__tablename__ = "attend"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
att_time = db.Column(db.Date)
status = db.Column(db.Integer,default=1) # 0 请假 ;1 正常出勤 ;2 迟到 ;3 早退 ;4 旷课
student_id = db.Column(db.Integer,db.ForeignKey("student.id"))
class Teacher(db.Model):
"""
老师表
老师与课程是多对一
"""
__tablename__ = "teacher"
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
name = db.Column(db.String(32))
age = db.Column(db.Integer)
gender = db.Column(db.Integer)# 1 男 0 女 -1 unknown
course_id = db.Column(db.Integer,db.ForeignKey("course.id"))
db.drop_all()
db.create_all()
1、新增保存数据
先创建数据会话,基于会话进行数据的增删改查
创建数据表实例,传入想要添加的数据
使用session保存数据
session.add(表实例)
session.commit()#添加后提交
添加传入数据的方式,不只是可以通过参数传递这一种方式,还可以像Django保存数据的方式,通过类属性方式传递;也可以使用字典解包方式传递
下面我们使用批量添加数据的方法应用这几个插入数据的方式
session.add_all([实例对象1,2,3...])
session.commit()
2、flask-sqlalchemy查询方法的使用
①all() 查询返回的所有的结果
print(Student.query.all())
print(Student.query.first())
# 后边必须跟all()方法,否则条件参数传不过去
print(Student.query.filter_by(age=18).all())
④filter()过滤器,条件查询,与filter_by条件使用不一样,需要类名.字段==条件进行查询
# 后边必须跟all()方法,否则条件参数传不过去
print(Student.query.filter(Student.age==18).all())
print(Student.query.order_by("age").all())
print(Student.query.order_by(db.desc("age")).all())
⑥get() 以主键查询
print(Student.query.get(3))
⑦offset() 偏移量 limit() 限制条数
一般offset和limit方法会结合使用
print(Student.query.offset(2).limit(2).all())
扩展
如果有offset和limit的情况下,通常会用这个方法进行分页查询。
分页:
用到参数
如:
3、修改数据
flask-sqlalchemy修改数据跟添加数据使用的方法一样,类似于字典的方法,进行赋值就相当于修改
先获取某一个数据,对该数据字段进行赋值,然后用session中的add方法进行更新修改提交
student = Student.query.get(4)
student.name = "唐老鸭"
session.add(student)
session.commit()
4、flask-sqlalchemy 删除数据
获取姓名为张三的数据,对其进行删除
# 删除数据
student = Student.query.filter_by(name="张三").first()
session.delete(student)
session.commit()
1、结构瑕疵
flask_sqlalchemy不同于Django中的数据模型,它不会自动创建id主键,如果我们有许多数据模型,那么每一个数据模型都需要去定义一个主键字段,就很不方便,所以我们可以使用面向对象的继承方法,继承db.Model类去定义一个id主键,然后创建的所有模型都继承我们新建的模型类方法,它及拥有db.Model中的字段方法,还新增了一个id主键,不必我们每一次去定义主键
使用抽象类来定义,定义完成数据模型继承此抽象类,并删除之前的id主键字段
同时我们还可以将数据添加、修改、删除的功能定义到这个抽象模型类,那种下次添加删除数据也不需要每次都写session.add()和session.commit(),也同时实现了代码的冗余。
class BaseModel(db.Model):
__abstract__ = True # 抽象表为True,代表当前类为抽象类,不会被创建
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
# 数据保存方法
def save(self):
session.add(self)
session.commit()
# 数据删除方法
def delete_data(self):
session.delete(self)
session.commit()
现在我们重新添加一条数据,使用该抽象类定义的方法保存和删除数据
添加数据
删除数据
2、数据映射瑕疵
flask-sqlslchemy 继承了 sqlalchemy的数据库抽象,在一对多和多对多关系当中, 需要双向映射
注意:
Sqllite数据库,在整形的orm类型可以传入字符
mysql数据库,插入非法类型,比如将字符插入整型,会直接插入0,并且进行waring警告