python Flask-ORM操作MYSQL数据库

  • Post author:
  • Post category:mysql




flask框架中使用数据库:

Flask-SQLAlchemy是在Flask中操作关系型数据库的拓展。是以面向模型对象的形式操作数据库,通过迁移完成建表



下载第三方包:

pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple

pip install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple



连接数据库的基本配置

from flask_sqlalchemy import SQLAlchemy
app=Flask(__name__)
#配置数据库的连接用户,启动地址端口号数据库名
app.config["SQLALCHEMY_DATABASE_URI"]="mysql://root:123456@127.0.0.1:3306/demo"
# 设置是否追踪数据库的增删改查,会有显著的开销,一般设置为False
app.config["SQLALCHEMY_TRACK_MOD/IFICATIONS"]=False
# 创建SQLAlchemy对象,,并与当前数据库关联,TCP连接
db=SQLAlchemy(app)



创建表模型

语法:

class 表名(db.Model):
	字段名=db.Column(db.数据类型(数值型Integer,字符传类型:String),primar_key=True)
	必须要有一个主键

创建表到数据库:
	db.create_all()



实例:

配置数据库

from flask import Flask,render_template,request,redirect
from flask_sqlalchemy import SQLAlchemy
app=Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"]="mysql://root:123456@127.0.0.1:3306/demo"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"]=False
db=SQLAlchemy(app)
在数据库中创建message的表

class Message(db.Model):
    id=db.Column(db.Integer,primary_key=True)
    name=db.Column(db.String(20))
    email=db.Column(db.String(20))
    address=db.Column(db.String(60))
    message=db.Column(db.String(100))
    
if __name__=='__main__':
    db.create_all()
    app.run(debug=True)



单表的增删改查



增:

语法:

方法一:

对象名= 表类名(字段名= "字段值")
db.session.add(user)  # 将user添加到这个TCP会话当中,这个session就代表这个链接会话

db.session.commit()	  #确认添加

实例:

book=Book()
book.name="射雕英雄传"
book.price=20
db.session.add(book)
db.session.commit()
方法二:

实例化表类
实例化名=表类名()
字段名=字段值
db.session.add(字段名) 
db.session.commit()	 

实例:

books=Book(name="射雕英雄传",price=21)

db.session.add(books)
db.session.commit()




语法

res=Book.query.filter_by(name="射雕英雄传").first()
db.session.delete(res)
db.session.commit()

实例:

res=Book.query.filter_by(name="射雕英雄传").first()
db.session.delete(res)
db.session.commit()




先查询需要修改的数据在进行修改

res=Book.query.filter_by(name="射雕英雄传").first()
res.name="天龙八部"
db.session.commit()




语法:

	模型类名.query.过滤器.查询执⾏器
	User.query.filter_by(id=1).执行器

查询执行器:

all()  返回查询到的所有结果,是一个列表, User.query.filter(User.name != 'wang').all()

first()  返回查询的第一个结果,User.query.filter(User.name != 'wang').first()

get()  返回主键对应的行, User.query.get(1)

count()  返回查询结果的数量 User.query.count()

paginate()  参数分别对应的是要查询的是第几页,每页几条数据,如果有错是否输出。 	

User.query.paginate(2, 3, False),这个例子是,每页三条数据,查询第二页的数据

实例:

res=Book.query.filter_by(name="射雕英雄传").first()



出现异常后回退函数 rollback:

db.session.rollback()



一对多的关系

什么是一对多:比如从班级的角度来说一个班级拥有多个学生即为一对多。 多对一:从学生的角度来说多个学生属于一个班级即为多对一。



ForeignKey的作用

必须要有主键或者外键

我们会在多的一方添加一个外键

语法:

me_id=db.Column(db.Integer,db.ForeignKey("publish.id"))

字段名=db.Column(db.Integer,db.ForeignKey("另外一张表名.它的主键"))

什么是外键:外键 ( foreign key ) 是用于建立和两个表数据之间的关系。通过将保存表中主键值的一列或多列添加到另一个表中,创建两个表之间的链接。这个列就成为第二个表的外键。

如图:

在这里插入图片描述



一查多(relationship)

使用这个必须要满足两个条件:


1. 使用这个必须在多的一方创建外键ForeignKey



2. 在一的那一方,建立跟多的那一方的关联属性


在修改了模型类必须执行数据库迁移文件

语法:

db.relationship("多的一方表模型名")



多查一(backref):

在relationship里添加第二个参数backref ,在多的一方查询一的这方

语法:

db.relationship("多的一方表模型名",backref="一的一方表模型名")



实例:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app=Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"]="mysql://root:123456@127.0.0.1:3306/demo"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"]=False
db=SQLAlchemy(app)

#创建图书表
class Book(db.Model):
   id= db.Column(db.Integer,primary_key=True)
   name=db.Column(db.String(64))
   price=db.Column(db.Integer)
   me_id=db.Column(db.Integer,db.ForeignKey("publish.id"))
   def __str__(self):
       return self.name
   def __repr__(self):
       return self.name

#创建出版社表
class Publish(db.Model):
    id=db.Column(db.Integer,primary_key=True)
    name=db.Column(db.String(20))
    address=db.Column(db.String(60))
    books=db.relationship("Book",backref="Pulish")

    def __str__(self):
        return self.name

    def __repr__(self):
        return self.name

在图书表中查询出版社的信息(多查一):

book=Book.query.filter_by(name="射雕英雄传").first()
    res=book.Pulish
    print("出版社名:%s" %res)

在出版社查询所有的图书信息:(一查多):

publish=Publish.query.filter(Publish.name=="北方出版社").first()
    books=publish.books
    print(books)



多对多

多对多是是建立第三方表来解决的,第三方表中有两张表的主键称为外键



多查多(relationship(secondary))

多对多的增删改查是比较麻烦的,relationship中的secondary对数据的操作是比较快捷的

语法:

字段名= db.relationship("另一张表的表模型", secondary="第三方表" )
他会在第三表查询到相关的数据在找到另一张表
__tablename__ = "tracher_class":
是指定的创建表的名字

实例:

班级表:

class Class(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    adress = db.Column(db.String(60))
    teachers = db.relationship("Teacher", secondary="tracher_class", backref="Class")

教师表:

class Teacher(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20))
    age = db.Column(db.Integer)
    sex = db.Column(db.String(2))

第三方表:

class Tracher_class(db.Model):
    __tablename__ = "tracher_class"
    id = db.Column(db.Integer, primary_key=True)
    teacher_id = db.Column(db.Integer, db.ForeignKey("teacher.id"))
    class_id = db.Column(db.Integer, db.ForeignKey("class.id"))



多个条件查询(filter)

模型类.query.filter(模型类.字段==False,User.last_login>begin_time,User.last_login<end_time).count()



排序(order_by)

升序语法:

模型类.query.order_by(模型类.字段名).limit(6)
limit:查询多少条数据



分页查询(paginate)

语法:

News.query.filter_by(category_id=cid).order_by(News.create_time.desc()).paginate(
page=当前页数,per_page=每页多少条数据)



查询总条数(count)

user_number = User.query.filter_by(is_admin=False).count()



数据迁移

在开发过程中,有时候需要修改数据库模型,比如新功能需要增加一个字段,在 Flask 代码中修改模型类后,要将新增的字段同步到数据库中。这时候是不能删表重建的。

在 Flask 中,可以使用数据库迁移来解决这个问题,数据库迁移可以追踪数据模型类的变化,然后把变动应用到数据库中,不会删表造成数据丢失。



数据迁移第三方包的下载(migrate)

数据迁移需要下载第三方包 ,命令:

pip install flask_migrate==2.1.1 
我的python版本是3.7的所以要指定版本



脚本操作第三方包下载命令:

pip install Flask-Script==2.0.6

实例:

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:123456@127.0.0.1:3306/demo"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)

manager = Manager(app)
Migrate(app,db)
manager.add_command("mysql(命令中有mysql就会以他来执行)",MigrateCommand)

if __name__ == '__main__':
    manager.run()



迁移命令

python 需要运行的文件.py mysql init

python 需要运行的文件.py mysql migrate -m "inintall (自定义版本号)"

执行迁移文件:
python manager.py mysql upgrade



表中增加新的字段,如何进行数据库的迁移

python manager.py mysql migrate -m 'role and info (版本号)'

执行迁移文件:
python manager.py mysql upgrade



迁移的回退

回到上一个版本:

python manager.py mysql downgrade

返回到某一个版本

python manager.py mysql downgrade ‘版本号’



分页



分页器查询(paginate)

分页查询,结果为查询集,如图

在这里插入图片描述

模型类.query.order_by(模型类.字段.desc()).paginate(当前页,  每页多少条数据)



使用执行器(all)进行分页

需要的参数有两个:从多少条数据开始、需要多少条数据才结束

使用方法如下:

模型类.query.order_by(User.uid.desc()).all()[offset:limit]
offset(从多少条开始数据):(当前页-1)*每页需要多少条数据
limit(需要多少条数据才结束): 当前页*每页需要多少条数据



使用offset 和limit进行分页查询

模型类.query.order_by(Food.total_count.desc(),Food.id.desc()).offset(offset).limit(page_size).all()



限制查询多少条数据(limit)

.limit(n) 查询N条数据



实现MySQL行锁的ORM语法:

语法:

db.session.query(模型类).filter(模型类.字段名).with_for_update().all()

这样就实现了MySQL的行锁了



不使用commit获取自动增长值

使用 db.session.flush()



flush和commit有什么区别

flush:预提交,等于提交到数据库内存,还未写入数据库文件;

语法:

	db.session.flush()

commit:就是把内存里面的东西直接写入,可以提供查询了;

语法:

	db.session.commit()



版权声明:本文为qq_48082548原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。