一、ORM 与 SQLAlchemy 简介

ORM 全称 Object Relational Mapping, 翻译过来叫对象关系映射。简单的说,ORM 将数据库中的表与面向对象语言中的类建立了一种对应关系。这样,我们要操作数据库,数据库中的表或者表中的一条记录就可以直接通过操作类或者类实例来完成。

SQLAlchemy 是Python 社区最知名的 ORM 工具之一,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型。

二、SQLAlchemy的使用

1、创建单表结构:



from sqlalchemy.ext.declarative import declarative_base  # 导入基类
from sqlalchemy import Column, Integer, String  # 数据类型

# Base = ORM基类 - 要按照ORM的规则定义你的类
Base = declarative_base()

class Users(Base):
    __tablename__ = "user"
    # 创建ID数据字段 , 那么ID是不是一个数据列呢? 也就是说创建ID字段 == 创建ID数据列
    # id = Column(数据类型,索引,主键,外键,等等)
    id = Column(Integer, primary_key=True, autoincrement=True,index=True)
    name = Column(String(32), nullable=False)  # nullable=False 不能为空


# 打开数据库的连接 -- 创建数据库引擎
from sqlalchemy import create_engine
# 创建数据库引擎
# engine = create_engine("mysql://scott:tiger@hostname/dbname",encoding='latin1', echo=True)
engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/SQLAlchemy_Pro?charset=utf8")

Base.metadata.create_all(engine)  # Base自动检索所有继承Base的ORM 对象 并且创建所有的数据表



2.单表的增删改查:



from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from creatTable import Users

# 创建引擎
engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/SQLAlchemy_Pro?charset=utf8")

Session = sessionmaker(engine)
db_session = Session()

# 1. 增加数据add(创建表结构的类名(字段名=添加的数据))
db_session.add(Users(name="ZWQ"))  # 相当于建立一条添加数据的sql语句
db_session.commit()  # 执行
db_session.close()   # 结束关闭

# 批量添加
db_session.add_all([Users(name="清风徐来"), Users(name="水波不兴")])
db_session.commit()
db_session.close()

# 2.查询 query(表结构的类名)
sqlres = db_session.query(Users)
print(sqlres)  # 直接翻译输出对应的SQL查询语句

res = db_session.query(Users).all()  # 返回表中所有数据对象
print(res)# [<creatTable.Users object at 0x00000000038A1B00>,<creatTable.Users object at 0x00000000038A1B70>]

for u in res:
    print(u.id, u.name)

res = db_session.query(Users).first()  # 取第一个,返回是对象
print(res.id, res.name)

res = db_session.query(Users).filter(Users.id == 3).first()  # 返回符合条件查询结果
print(res.name)

res = db_session.query(Users).filter(Users.id <= 2, Users.name == "ZWQ").all() # filter中的条件可以是模糊条件,多个条件
for u in res:
    print(u.id,u.name)

# 3.更改数据 update({k:v})
res = db_session.query(Users).filter(Users.id == 1).update({"name":"DragonFire"})
print(res)
db_session.commit()

res = db_session.query(Users).update({"name":"ZWQ"})  # 全部修改,返回修改的数据个数
print(res)
db_session.commit()

# 4.删除 delete()结合查询条件删除
res = db_session.query(Users).filter(Users.id == 1).delete()  # 删除否合条件的数据,返回删除数量
print(res)
db_session.commit()

res = db_session.query(Users).delete()  # 删除表中所有数据,返回删除数量
print(res)
db_session.commit()



 

3.创建外键关联的表结构:



from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

from sqlalchemy import Column,Integer,String,ForeignKey
from sqlalchemy.orm import relationship

class Student(Base):
    __tablename__ = "student"
    id = Column(Integer,primary_key=True)
    name = Column(String(32),nullable=False)
    sch_id = Column(Integer,ForeignKey("school.id"))  # 关联的表的字段,表间的关系

    stu2sch = relationship("School",backref="sch2stu")  # 写在哪边那边就是正向查询,对象间的关系,backref(反向查询)


class School(Base):
    __tablename__ = "school"
    id = Column(Integer,primary_key=True)
    name = Column(String(32),nullable=False)


from sqlalchemy import create_engine
engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/SQLAlchemy_Pro?charset=utf8")

Base.metadata.create_all(engine)



 4、外键关联的表添加与查询操作:



from sqlalchemy.orm import sessionmaker
from creatTableFk import engine   
from creatTableFk import Student,School  # 导入创建表结构的类

Session = sessionmaker(engine)

db_session = Session()

# 1.添加数据
db_session.add(School(name="NCU"))
db_session.commit()

# relationship  正向添加
stu = Student(name="清风徐来",stu2sch=School(name="NCU"))
db_session.add(stu)
db_session.commit()

# relationship  反向添加
sch = School(name="NCU")
sch.sch2stu = [Student(name="YWB"),Student(name="CT")]
db_session.add(sch)
db_session.commit()

# 2.查询
res = db_session.query(Student).all()
for stu in res:
    print(stu.name,stu.stu2sch.name)  # 正向跨表

res = db_session.query(School).all()
for sch in res:
    for stu in sch.sch2stu:
        print(sch.name,stu.name)  # 反向跨表



 

5.多对多的表的创建



from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer, ForeignKey, create_engine
from sqlalchemy.orm import relationship

Base = declarative_base()


# 多对多关联通过第三张表关联,sqlalchemy要自己创建第三张表
class Girl(Base):
    __tablename__ = "girls"
    id = Column(Integer, primary_key=True)
    name = Column(String(32), nullable=False)

    g2b = relationship("Boy", backref="b2g", secondary="hotels")


class Boy(Base):
    __tablename__ = "boys"
    id = Column(Integer, primary_key=True)
    name = Column(String(32), nullable=False)


class Hotel(Base):
    __tablename__ = "hotels"
    id = Column(Integer, primary_key=True)
    boy_id = Column(Integer, ForeignKey("boys.id"), nullable=False)
    girl_id = Column(Integer, ForeignKey("girls.id"), nullable=False)


engine = create_engine("mysql+pymysql://root:@127.0.0.1:3306/SQLAlchemy_Pro?charset=utf8")
Base.metadata.create_all(engine)



6.多对多表数据的添加与查询:



from sqlalchemy.orm import sessionmaker

from CreateTableM2M import engine

Session = sessionmaker(engine)
db_session = Session()

from CreateTableM2M import Girl,Boy

# 1.增加数据
# relationship 正向添加
g = Girl(name="ZLY",g2b=[Boy(name="ZWQ"),Boy(name="FSF")])
db_session.add(g)
db_session.commit()

# relationship 反向添加
b = Boy(name="ZS")
b.b2g = [Girl(name="罗玉凤"),Girl(name="娟儿"),Girl(name="芙蓉姐姐")]
db_session.add(b)
db_session.commit()

# 2.查询
# relationship 正向
res = db_session.query(Girl).all()
for g in res:
    for b in g.g2b:
        print(g.name,b.name)

# relationship 反向
res = db_session.query(Boy).all()
for b in res:
    for g in b.b2g:
        print(b.name,g.name)



7. 高级ORM操作




flask_sqlalchemy 对应flask版本_User

flask_sqlalchemy 对应flask版本_数据库_02

1 from CreateTable import Users,engine
  2 from sqlalchemy.orm import sessionmaker
  3 from CreateTableForeignKey import Student
  4 
  5 Session = sessionmaker(engine)
  6 db_session = Session()
  7 
  8 # 查询数据表操作
  9 # and or
 10 from sqlalchemy.sql import and_ , or_,desc
 11 ret = db_session.query(Users).filter(and_(Users.id > 3, Users.name == 'DragonFire')).all()
 12 ret = db_session.query(Users).filter(or_(Users.id < 2, Users.name == 'DragonFire')).all()
 13 
 14 ret = db_session.query(Users).filter(
 15     or_(
 16         Users.id < 2,
 17         and_(
 18             Users.name == 'eric',
 19             Users.id > 3
 20         ),
 21         Users.name != ""
 22     )
 23 )
 24 print(ret)
 25 select * from User where id<2 or (name="eric" and id>3) or extra != ""
 26 
 27 
 28 # 查询所有数据
 29 r1 = db_session.query(User).all()
 30 
 31 查询数据 指定查询数据列 加入别名
 32 r2 = db_session.query(Student.name.label('username'), Student.id).first()
 33 print(r2.id,r2.username) # 15 NBDragon
 34 
 35 # 表达式筛选条件
 36 r3 = db_session.query(User).filter(User.name == "DragonFire").all()
 37 
 38 # 原生SQL筛选条件
 39 r4 = db_session.query(User).filter_by(name='DragonFire').all()
 40 r5 = db_session.query(Users).filter_by(name='DragonFire').first()
 41 
 42 字符串匹配方式筛选条件 并使用 order_by进行排序
 43 r6 = db_session.query(Student).order_by(Student.name.desc()).all()
 44 for i in r6:
 45     print(i.id,i.name)
 46 
 47 原生SQL查询
 48 from sqlalchemy.sql import text
 49 r7 = db_session.query(User).from_statement(text("SELECT * FROM User where name=:name")).params(name='DragonFire').all()
 50 
 51 # 筛选查询列
 52 # query的时候我们不在使用User ORM对象,而是使用User.name来对内容进行选取
 53 user_list = db_session.query(User.name).all()
 54 print(user_list)
 55 for row in user_list:
 56     print(row.name)
 57 
 58 # 别名映射  name as nick
 59 user_list = db_session.query(User.name.label("nick")).all()
 60 print(user_list)
 61 for row in user_list:
 62     print(row.nick) # 这里要写别名了
 63 
 64 # 筛选条件格式
 65 user_list = db_session.query(User).filter(User.name == "DragonFire").all()
 66 user_list = db_session.query(User).filter(User.name == "DragonFire").first()
 67 user_list = db_session.query(User).filter_by(name="DragonFire").first()
 68 for row in user_list:
 69     print(row.nick)
 70 
 71 # 复杂查询
 72 from sqlalchemy.sql import text
 73 user_list = db_session.query(User).filter(text("id<:value and name=:name")).params(value=3,name="DragonFire")
 74 
 75 # 查询语句
 76 from sqlalchemy.sql import text
 77 user_list = db_session.query(User).filter(text("select * from User id<:value and name=:name")).params(value=3,name="DragonFire")
 78 
 79 # 排序 :
 80 user_list = db_session.query(User).order_by(User.id).all()
 81 user_list = db_session.query(User).order_by(User.id.desc()).all()
 82 for row in user_list:
 83     print(row.name,row.id)
 84 
 85 #其他查询条件
 86 """
 87 ret = session.query(User).filter_by(name='DragonFire').all()
 88 ret = session.query(User).filter(User.id > 1, User.name == 'DragonFire').all()
 89 ret = session.query(User).filter(User.id.in_(session.query(User.id).filter_by(name='DragonFire'))).all() 子查询
 90 from sqlalchemy import and_, or_
 91 ret = session.query(User).filter(and_(User.id > 3, User.name == 'DragonFire')).all()
 92 ret = session.query(User).filter(or_(User.id < 2, User.name == 'DragonFire')).all()
 93 
 94 
 95 
 96 
 97 # 限制
 98 ret = db_session.query(User)[1:2]
 99 
100 # 排序
101 ret = db_session.query(User).order_by(User.name.desc()).all()
102 ret = db_session.query(User).order_by(User.name.desc(), User.id.asc()).all()
103 
104 # 分组
105 from sqlalchemy.sql import func
106 
107 ret = db_session.query(User).group_by(User.extra).all()
108 ret = db_session.query(
109     func.max(User.id),
110     func.sum(User.id),
111     func.min(User.id)).group_by(User.name).all()
112 
113 ret = db_session.query(
114     func.max(User.id),
115     func.sum(User.id),
116     func.min(User.id)).group_by(User.name).having(func.min(User.id) >2).all()
117 """
118 
119 # 关闭连接
120 db_session.close()
121 
122 
123 ret = db_session.query(Student).filter(Student.id.between(1, 3)).all() # between 大于1小于3的
124 for i in ret:
125     print(i.id,i.name)
126 ret = db_session.query(Student).filter(~Student.id.in_([1,4])).all() # in_([1,3,4]) 只查询id等于1,3,4的
127 for i in ret:
128     print(i.id,i.name)
129 ret = session.query(User).filter(~User.id.in_([1,3,4])).all() # ~xxxx.in_([1,3,4]) 查询不等于1,3,4的
130 # 通配符
131 ret = db_session.query(Student).filter(Student.name.like('%e%')).all()
132 
133 
134 ret = db_session.query(Student).filter(~Student.name.like('Z%')).all()
135 for i in ret:
136     print(i.id,i.name)
137 
138 
139 
140 高级版更新操作
141 from my_create_table import User,engine
142 from sqlalchemy.orm import sessionmaker
143 
144 Session = sessionmaker(engine)
145 db_session = Session()
146 
147 #直接修改
148 db_session.query(Student).filter(Student.id > 3).update({Student.name: Student.name + "099"}, synchronize_session=False)
149 db_session.commit()
150 
151 db_session.query(Student).filter(Student.id > 3).update({"name": Student.name + "123"}, synchronize_session=False)
152 db_session.commit()
153 
154 
155 #在原有值基础上添加 - 1
156 db_session.query(User).filter(User.id > 0).update({User.name: User.name + "099"}, synchronize_session=False)
157 
158 #在原有值基础上添加 - 2
159 db_session.query(User).filter(User.id > 0).update({"age": User.age + 1}, synchronize_session="evaluate")
160 db_session.commit()


View Code


三、Flask_SQLAlchemy

1. 安装 Flask-SQLAlchemy模块,pip安装 

  pip install Flask-SQLAlchemy

2.先创建一个Flask项目

3.基于这个Flask项目,加入Flask-SQLAlchemy让项目变得生动起来



1 from flask import Flask
 2 
 3 # 导入Flask-SQLAlchemy中的SQLAlchemy
 4 from flask_sqlalchemy import SQLAlchemy
 5 
 6 # 实例化SQLAlchemy
 7 db = SQLAlchemy()
 8 # PS : 实例化SQLAlchemy的代码必须要在引入蓝图之前
 9 
10 from .views.users import user
11 
12 
13 def create_app():
14     app = Flask(__name__)
15 
16     # 初始化App配置 这个app配置就厉害了,专门针对 SQLAlchemy 进行配置
17     # SQLALCHEMY_DATABASE_URI 配置 SQLAlchemy 的链接字符串儿
18     app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:DragonFire@127.0.0.1:3306/dragon?charset=utf8"
19     # SQLALCHEMY_POOL_SIZE 配置 SQLAlchemy 的连接池大小
20     app.config["SQLALCHEMY_POOL_SIZE"] = 5
21     # SQLALCHEMY_POOL_TIMEOUT 配置 SQLAlchemy 的连接超时时间
22     app.config["SQLALCHEMY_POOL_TIMEOUT"] = 15
23     app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
24 
25     # 初始化SQLAlchemy , 本质就是将以上的配置读取出来
26     db.init_app(app)
27 
28     app.register_blueprint(user)
29 
30     return app
31 
32 MyApp/__init__.py



4.建立models.py ORM模型文件



1 from MyApp import db
 2 
 3 Base = db.Model # 这句话你是否还记的?
 4 # from sqlalchemy.ext.declarative import declarative_base
 5 # Base = declarative_base()
 6 # 每一次我们在创建数据表的时候都要做这样一件事
 7 # 然而Flask-SQLAlchemy已经为我们把 Base 封装好了
 8 
 9 # 建立User数据表
10 class Users(Base): # Base实际上就是 db.Model
11     __tablename__ = "users"
12     __table_args__ = {"useexisting": True}
13     # 在SQLAlchemy 中我们是导入了Column和数据类型 Integer 在这里
14     # 就和db.Model一样,已经封装好了
15     id = db.Column(db.Integer,primary_key=True)
16     username = db.Column(db.String(32))
17     password = db.Column(db.String(32))
18 
19 
20 if __name__ == '__main__':
21     from MyApp import create_app
22     app = create_app()
23     # 这里你要回顾一下Flask应用上下文管理了
24     # 离线脚本:
25     with app.app_context():
26         db.drop_all()
27         db.create_all()
28 
29 MyApp/models.py



5.实现一个简单的用户管理,登录视图



1 from flask import Blueprint, request, render_template, redirect
 2 from MyApp.models import User,db
 3 
 4 users = Blueprint("user",__name__)
 5 
 6 @users.route("/add_user",methods=["POST","GET"])
 7 def add_user():
 8     if request.method == "GET":
 9         return render_template("add_user.html")
10     else:
11         username = request.form.get("username")
12         db.session.add(User(name=username))
13         db.session.commit()
14         return redirect("/user_list")
15 
16 @users.route("/user_list",methods=["POST","GET"])
17 def user_list():
18     res = User.query.all()
19     print(res)
20     return render_template("user_list.html",user_list=res)
21 
22 
23 @users.route("/del/<uid>",methods=["POST","GET"])
24 def delete_user(uid):
25     res = User.query.filter(User.id == int(uid)).delete()
26     db.session.commit()
27     print(res)
28     return redirect("/user_list")
29 
30 
31 
32 @user.route("/login",methods=["POST","GET"])
33 def user_login():
34     if request.method == "POST":
35         username = request.form.get("username")
36         password = request.form.get("password")
37 
38         # SQlalchemy需要这样做
39         # from sqlalchemy.orm import sessionmaker
40         # Session = sessionmaker(engine)
41         # db_sesson = Session()
42         # 现在不用了,因为 Flask-SQLAlchemy 也已经为我们做好会话打开的工作
43         # 我们在这里做个弊:
44         db.session.add(Users(username=username,password=password))
45         db.session.commit()
46 
47         # 然后再查询
48         user_info = Users.query.filter(Users.username == username and User.password == password).first()
49         print(user_info.username)
50         if user_info:
51             return f"登录成功{user_info.username}"
52 
53     return render_template("login.html")



其实Flask-SQLAlchemy比起SQLAlchemy更加的简单自如,用法几乎一模一样,就是在配置和启动上需要注意与Flask的配合就好啦