Flask数据库模型之flask-sqlalchemy的使用(三)

一、flask-sqlalchemy的安装和配置

  sqlalchemy 是python开发的一个ORM(数据库映射)模块: 将python面向对象的类映射为数据库的表,通过映射关系来完成数据库的操作,降低数据库操作的难度和繁琐程度。类似的模块还有(peewee)。

  Flask将sqlalchemy进行封装,封装到自己的项目当中, sqlalchemy和flask-sqlalchemy的操作有一部分不同。

1、安装flask-sqlalchemy

pip install flask-sqlalchemy

在这里插入图片描述
2、连接数据库

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 自增长

二、flask-sqlalchemy中的数据表关系

1、一对一关系
在一个表里记录另一个表的字段

2、一对多关系

使用字段类型db.Foreignkey("主键表.id")

在这里插入图片描述
3、多对多关系

# 关联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()


三、flask-sqlalchemy中的增删改查

1、新增保存数据
先创建数据会话,基于会话进行数据的增删改查
在这里插入图片描述

创建数据表实例,传入想要添加的数据
在这里插入图片描述
使用session保存数据

session.add(表实例)
session.commit()#添加后提交

在这里插入图片描述
在这里插入图片描述

添加传入数据的方式,不只是可以通过参数传递这一种方式,还可以像Django保存数据的方式,通过类属性方式传递;也可以使用字典解包方式传递

下面我们使用批量添加数据的方法应用这几个插入数据的方式

session.add_all([实例对象1,2,3...])
session.commit()

在这里插入图片描述
在这里插入图片描述

2、flask-sqlalchemy查询方法的使用
①all() 查询返回的所有的结果

print(Student.query.all())

在这里插入图片描述
②first()查询返回的第一个结果

print(Student.query.first())

在这里插入图片描述
③filter_by()过滤器,条件查询

# 后边必须跟all()方法,否则条件参数传不过去
print(Student.query.filter_by(age=18).all())

在这里插入图片描述
④filter()过滤器,条件查询,与filter_by条件使用不一样,需要类名.字段==条件进行查询

# 后边必须跟all()方法,否则条件参数传不过去
print(Student.query.filter(Student.age==18).all())

在这里插入图片描述
⑤order_by() 排序查询
升序查询

print(Student.query.order_by("age").all())

在这里插入图片描述
降序查询
使用sqlalchemy的字段desc进行降序

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的情况下,通常会用这个方法进行分页查询
分页:
用到参数

  • page 页码 1
  • page_size 单页条数 10

如:

  • 第1页 数据 0-10
  • 第2页 数据 10-20
  • 第3页 数据 20-30
  • 第n页 数据 (n-1)page_size - n*page_size

使用offset和limit进行分页的flask使用模板:
在这里插入图片描述

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()

在这里插入图片描述
在这里插入图片描述

四、基于flask_sqlalchemy的数据库操作优化

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警告
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孜孜孜孜不倦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值