flask_sqlalchemy组件
先来个示例:
1.安装flask_sqlalchemy
pip install flask_sqlalchemy
2.项目准备

我们准备一个干净的flask项目,下载地址:https://pan.baidu.com/s/1hn_GhToYbfSpDJu8ASLJHg
目录结构如上,下面我们基于这个项目,加入flask_sqlachemy使项目操作数据库
1.加入flask_sqlalchemy组件
flask_sqlalchemy_project/__init__.py
from flask import Flask
# 导入Flask-SQLAlchemy中的SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
# 实例化SQLAlchemy
db = SQLAlchemy()
# PS : 实例化SQLAlchemy的代码必须要在引入蓝图之前
from flask_sqlalchemy_lesson.views import user
def create_app():
app = Flask(__name__)
# 初始化App配置 这个app配置就厉害了,专门针对 SQLAlchemy 进行配置
# SQLALCHEMY_DATABASE_URI 配置 SQLAlchemy 的链接字符串儿
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:@127.0.0.1:3306/dr?charset=utf8"
# SQLALCHEMY_POOL_SIZE 配置 SQLAlchemy 的连接池大小
app.config["SQLALCHEMY_POOL_SIZE"] = 5
# SQLALCHEMY_POOL_TIMEOUT 配置 SQLAlchemy 的连接超时时间
app.config["SQLALCHEMY_POOL_TIMEOUT"] = 15
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# 初始化SQLAlchemy , 本质就是将以上的配置读取出来
db.init_app(app)
app.register_blueprint(user)
return app
2.建立models.py文件,ORM模型文件
from flask_sqlalchemy import SQLAlchemy
from flask_sqlalchemy_lesson import db
# Base = db.Model # 这句话你是否还记的?
# from sqlalchemy.ext.declarative import declarative_base
# Base = declarative_base()
# 每一次我们在创建数据表的时候都要做这样一件事
# 然而Flask-SQLAlchemy已经为我们把 Base 封装好了
# 建立User数据表
class Users(db.Model):
# 指定一个表名
__tablename__="user_flask"
# 在SQLAlchemy 中我们是导入了Column和数据类型 Integer 在这里就和db.Model一样,已经封装好了
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(32),nullable=False)
if __name__ == '__main__':
from day101_SQLAlchemy.flask_sqlalchemy_lesson import create_app # 导入数据库的
app = create_app()
db.create_all(app=app)
3.蓝图函数中user.py
from flask import Blueprint
from day101_SQLAlchemy.flask_sqlalchemy_lesson.models import Users,db
user_bp = Blueprint("user_bp",__name__)
@user_bp.route("/add_user/<username>",methods=["GET","POST"])
def add_user(username):
u = Users(name=username)
db.session.add(u) # 打开数据库连接窗口
db.session.commit()
return "200 add success"
@user_bp.route("/get_user/<username>",methods=["GET","POST"])
def get_user(username):
u = Users.query.filter(Users.name == username).first()
return u.name
4.运行项目manage.py文件
from day101_SQLAlchemy.flask_sqlalchemy_lesson import create_app
app = create_app()
if __name__ == '__main__':
app.run()
基本使用
安装:
pip3 install sqlalchemy
注:SQLAlchemy无法修改表结构,如果需要可以使用SQLAlchemy开发者开源的另外一个软件Alembic来完成,官网doc:http://docs.sqlalchemy.org/en/latest/core/expression_api.html
原生SQL
使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句
#!/usr/bin/env python3
#_*_ coding:utf-8 _*_
#Author:wd
from sqlalchemy import create_engine
engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student", max_overflow=5)#创建连接,允许溢出5个连接
result = engine.execute('select * from student')#使用excute执行原生sql
print(result.fetchall())#获取所有结果,与pymyql类似
事务
#!/usr/bin/env python3
#_*_ coding:utf-8 _*_
#Author:wd
from sqlalchemy import create_engine
engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student", max_overflow=5)#创建连接,允许溢出5个连接
result = engine.execute('select * from student')#使用excute执行原生sql
with engine.begin() as conn: #事务操作
conn.execute("insert into student (name, age, res_date) values ('weikang', 33, '1992-11-11')")
print(result.fetchall())#获取所有结果,与pymyql类似
建表
定义数据表,才能进行sql表达式的操作,毕竟sql表达式的表的确定,是sqlalchemy制定的,如果数据库已经存在了数据表还需要定义么?当然,这里其实是一个映射关系,如果不指定,查询表达式就不知道是附加在那个表的操作,当然定义的时候,注意表名和字段名,代码和数据的必须保持一致。定义好之后,就能创建数据表,一旦创建了,再次运行创建的代码,数据库是不会创建的。
sqlalchemy内部组件调用顺序为:使用 Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 进行数据库操作。Engine使用Schema Type创建一个特定的结构对象,之后通过SQL Expression Language将该对象转换成SQL语句,然后通过 ConnectionPooling 连接数据库,再然后通过 Dialect 执行SQL,并获取结果。
TIPS:使用类的方式和使用metadata方式创建表时候区别在于metadata可以不指定主键,而是用class方式必须要求有主键。
demo1:
from sqlalchemy import create_engine,Table,Column,Integer,String,ForeignKey,MetaData
engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student?charset=gbk",
encoding="utf-8",
echo=True,
max_overflow=5
)
#?charset是字符集编码,echo=True打印输出信息和执行的sql语句默认Flase,max_overflow=5允许溢出连接池连接数量
meta=MetaData()#生成源类
#定义表结构
user=Table('user',meta,
Column('id',Integer,nullable=Table,autoincrement=True,primary_key=True),
Column('name',String(20),nullable=True),
Column('age',Integer,nullable=True)
)
host=Table('host',meta,
Column('ip',String(20),nullable=True),
Column('hostname',String(20),nullable=True),
)
meta.create_all(engine)#创建表,如果存在则忽视
demo2:
使用orm基类创建
#!/usr/bin/env python3
#_*_ coding:utf-8 _*_
#Author:wd
from sqlalchemy import create_engine,Table,Column,Integer,String,ForeignKey,MetaData,Date
from sqlalchemy.ext.declarative import declarative_base
engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student?charset=gbk",
encoding="utf-8",
echo=True,
max_overflow=5
)
#?charset是字符集编码,echo=True打印输出信息和执行的sql语句默认Flase,max_overflow=5允许溢出连接池连接数量
base=declarative_base()#生成ORM基类
#定义表结构
class User(base):
__tablename__='book' #表明
id = Column(Integer, primary_key=True)
name=Column(String(32))
date=Column(Date)
base.metadata.create_all(engine)#创建表,如果存在则忽视
orm增删改查
增
#!/usr/bin/env python3
#_*_ coding:utf-8 _*_
#Author:wd
from sqlalchemy import create_engine,Table,Column,Integer,String,ForeignKey
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student?charset=gbk",
max_overflow=5,
echo=True)
#数据库连接信息为,连接类型://用户名:密码@数据库地址:端口/数据库名字?编码
#max_overflow创建连接,允许溢出5个连接,echo=True,输出相应的sql信息到控制台,方便调试。
base=declarative_base()#生成orm基类
class user(base): #映射表
__tablename__='user'
id=Column(Integer,autoincrement=True,primary_key=True)
name=Column(String(20))
age=Column(Integer)
sessoion_class=sessionmaker(bind=engine)#创建与数据库的会话类,这里的sessoion_class是类
Session=sessoion_class()#生成会话实例
user1=user(name='wd',age=22)#生成user对象
Session.add(user1) #添加user1,可以使用add_all,参数为列表或者tuple
Session.commit() #提交
#Session.rollback() #回滚
Session.close() #关闭会话
删
data=Session.query(user).filter(user.age==33).delete()
Session.commit() #提交
Session.close() #关闭会话
改
#data=Session.query(user).filter(user.age>20).update({"name":'jarry'})#update语法
data=Session.query(user).filter(user.age==22).first()#面向对象语法
data.name='coco'#如果data中数据多条需要使用for循环设置
Session.commit() #提交
Session.close() #关闭会话
查
#!/usr/bin/env python3
#_*_ coding:utf-8 _*_
#Author:wd
from sqlalchemy import create_engine,Table,Column,Integer,String,ForeignKey
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student?charset=gbk",
max_overflow=5,
echo=True)
#数据库连接信息为,连接类型://用户名:密码@数据库地址:端口/数据库名字?编码
#max_overflow创建连接,允许溢出5个连接,echo=True,输出相应的sql信息到控制台,方便调试。
base=declarative_base()#生成orm基类
class user(base): #映射表
__tablename__='user'
id=Column(Integer,autoincrement=True,primary_key=True)
name=Column(String(20))
age=Column(Integer)
def __repr__(self): #定义
return "(%s,%s,%s)" % (self.id,self.name,self.age)
sessoion_class=sessionmaker(bind=engine)#创建与数据库的会话类,这里的sessoion_class是类
Session=sessoion_class()#生成会话实例
#data=Session.query(user).get(2) #get语法获取primrykey中的关键字,在这里主键为id,获取id为2的数据
#data=Session.query(user).filter(user.age>22,user.name=='mack').first()
#filter语法两个等于号,filter_by语法一个等于号,可以有多个filter,如果多个数据返回列表,first代表获取第一个,为all()获取所有
data=Session.query(user).filter(user.age>20,user.name.in_(['mack','wd'])).all()#in语法
print(data[0]) #打印第一个结果
Session.commit() #提交,如果回滚的话,数据将不存在了
Session.close() #关闭会话
常用查询其他操作
##获取所有数据
data=Session.query(user).all()#获取user表所有数据
for i in data:
print(i)
##统计
#count=Session.query(user).count()#获取所有的条数
count=Session.query(user).filter(user.name.like("ja%")).count()#获取某些条数
print(count)
##分组
from sqlalchemy import func#需要导入func函数
res=Session.query(func.count(user.name),user.name).group_by(user.name).all()
print(res)
外间关联
TIPS:设置外检的另一种方式 ForeignKeyConstraint(['other_id'], ['othertable.other_id'])
#!/usr/bin/env python3
#_*_ coding:utf-8 _*_
#Author:wd
from sqlalchemy import create_engine,Table,Column,Integer,String,ForeignKey
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student?charset=gbk",
encoding="utf-8",
echo=True,
max_overflow=5
)
#?charset是连接数据库的字符集编码(和数据库的编码一样),echo=True打印输出信息和执行的sql语句默认Flase,max_overflow=5允许溢出连接池连接数量
Base=declarative_base()
class user(Base):
__tablename__='user'
id=Column(Integer,primary_key=True,autoincrement=True)
name=Column(String(20))
age=Column(Integer)
def __repr__(self):
return "<id:%s,name:%s,age:%s>"%(self.id,self.name,self.age)
class host(Base):
__tablename__='host'
user_id=Column(Integer,ForeignKey('user.id'))#user_id关联user表中的id
hostname=Column(String(20))
ip=Column(String(20),primary_key=True)
host_user=relationship('user',backref='user_host')
#通过host_user查询host表中关联的user信息,通过user_host,在user表查询关联的host,与生成的表结构无关,只是为了方便查询
def __repr__(self):
return "<user_id:%s,hostname:%s,ip:%s>"%(self.user_id,self.hostname,self.ip)
Base.metadata.create_all(engine)
Session_class=sessionmaker(bind=engine)
Session=Session_class()
host1=Session.query(host).first()
print(host1.host_user)
print(host1)
user1=Session.query(user).first()
print(user1.user_host)
多外键关联一个表中的一个字段
应用场景:当我们购物时候,你会发现有一个收发票地址,和一个收货地址。关系如下:默认情况下,发票地址和收获地址是一致的,但是也有可能我想买东西送给别人,而发票要自己留着,那收货的地址和寄送发票的地址可以不同。即:同一个人的两个收获地址可以不同,多个收获地址关联同一个人。
#!/usr/bin/env python3
#_*_ coding:utf-8 _*_
#Author:wd
from sqlalchemy import Integer, ForeignKey, String, Column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
class Customer(Base):
__tablename__ = 'customer'
id = Column(Integer, primary_key=True)
name = Column(String)
billing_address_id = Column(Integer, ForeignKey("address.id"))
shipping_address_id = Column(Integer, ForeignKey("address.id"))
billing_address = relationship("Address", foreign_keys=[billing_address_id])
shipping_address = relationship("Address", foreign_keys=[shipping_address_id])
#同时关联同一个字段,使用relationship需要指定foreign_keys,为了让sqlalchemy清楚关联的外键
class Address(Base):
__tablename__ = 'address'
id = Column(Integer, primary_key=True)
street = Column(String)
city = Column(String)
state = Column(String)
多对多外键关联
很多时候,我们会使用多对多外键关联,例如:书和作者,学生和课程,即:书可以有多个作者,而每个作者可以写多本书,orm提供了更简单方式操作多对多关系,在进行删除操作的时候,orm会自动删除相关联的数据。
表结构创建
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd from sqlalchemy import Column,Table,String,Integer,ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine from sqlalchemy.orm import relationship engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student?charset=gbk", encoding="utf-8", echo=True, max_overflow=5 ) Base=declarative_base() stu_cour=Table('stu_cour',Base.metadata, Column('stu_id',Integer,ForeignKey('student.id')), Column('cour_id',Integer,ForeignKey('course.id')) ) class student(Base): __tablename__='student' id=Column(Integer,autoincrement=True,primary_key=True) stu_name=Column(String(32)) stu_age=Column(String(32)) courses=relationship('course',secondary=stu_cour,backref='students') #course是关联的第一张表,stu_cour是关联的第二张表,当然,也可以在第三张关联表中使用两个relationship关联student表和course表 def __repr__(self): return '<%s>'%self.stu_name class course(Base): __tablename__='course' id=Column(Integer,autoincrement=True,primary_key=True) cour_name=Column(String(32)) def __repr__(self): return '<%s>'%self.cour_name Base.metadata.create_all(engine) 创建表结构 建表
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd from sqlalchemy import Column,Table,String,Integer,ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine from sqlalchemy.orm import relationship engine=create_engine("mysql+pymysql://stu:1234qwer@10.0.0.241:3307/student?charset=gbk", encoding="utf-8", echo=True, max_overflow=5 ) Base=declarative_base() stu_cour=Table('stu_cour',Base.metadata, Column('stu_id',Integer,ForeignKey('student.id')), Column('cour_id',Integer,ForeignKey('course.id')) ) class student(Base): __tablename__='student' id=Column(Integer,autoincrement=True,primary_key=True) stu_name=Column(String(32)) stu_age=Column(String(32)) courses=relationship('course',secondary=stu_cour,backref='students') #course是关联的第一张表,stu_cour是关联的第二张表,当然,也可以在第三张关联表中使用两个relationship关联student表和course表 def __repr__(self): return '<%s>'%self.stu_name class course(Base): __tablename__='course' id=Column(Integer,autoincrement=True,primary_key=True) cour_name=Column(String(32)) def __repr__(self): return '<%s>'%self.cour_name Base.metadata.create_all(engine) 创建表结构 建表
session_class=sessionmaker(bind=engine) session=session_class() stu_obj=session.query(student).filter(student.stu_name=='wd').first() print(stu_obj.courses)#查询wd学生所报名的课程 cour_obj=session.query(course).filter(course.cour_name=='python').first() print(cour_obj.students)#查询报名python课程所对应的课程 session.commit() 查询
session_class=sessionmaker(bind=engine) session=session_class() cour_obj=session.query(course).filter(course.cour_name=='python').first() session.delete(cour_obj)#删除python课程 session.commit()

浙公网安备 33010602011771号