开发者日志sqlalchemy 7.31
sqlalchemy 创建表
1. 使用sqlalchemy创建一个表
-
引入方法
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String Model = declarative_base() # 创建基类,相当于Django中的 models.Model,被各个数据表类所继承
-
创建表
class Users(Model): # Users是对象 __tablename__ = 'users' # 映射到数据的表 id = Column(Integer, primary_key=True, autoincrement=True) # 主键 自增 name = Column(String(32), index=True, nullable=False, unique=True) # 普通索引 排序用到 1是索引2是首字母 重复首字母 看索引
-
使用引擎创建数据库
# 创建数据库的引擎 from sqlalchemy.engine import create_engine engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/sqlalchemy?charset=utf8") # 检索所有继承 Model 的Object 并在 engine 指向的数据库中创建 所有的表 Model.metadata.create_all(engine) # Model.metadata.drop_all(engine) # 删除所有
关于索引,
上面的创建表的形式使BTREE索引,还有hash索引
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
参考博客:https://blog.csdn.net/kidoo1012/article/details/70207519
2. 增删改查 crud
create read update delete
-
引入数据库,以及引擎窗口操作
from sqlalchemy.orm import sessionmaker # 创建数据表操作对象 sessionmaker from create_table import engine, Users # 导入引擎 session = sessionmaker(engine) # 新建 sqlalchemy 这个数据库的查询窗口 db_session = session() # 打开查询窗口
-
增加数据
u = Users(name='JWB') # 新建insert语句 = insert into db_session.add(u) # 将insert语句移动到 db_session 查询窗口 db_session.commit() # 执行查询窗口中的所有语句 db_session.close() # 关闭查询窗口
-
增加多条数据
u_list = [Users(name='YWB'), Users(name='dragonfire')] # 新建insert语句 = insert into db_session.add_all(u_list) # 将insert语句移动到 db_session 查询窗口 db_session.commit() # 执行查询窗口中的所有语句 db_session.close() # 关闭查询窗口
-
查询数据
res = db_session.query(Users).all() # 查询所有数据 # [<create_table.Users object at 0x00000000038ADC18>, <create_table.Users object at 0x00000000038ADBA8>] res = db_session.query(Users) # 不写默认是all,但是不提倡 for u in res: print(u.id, u.name) res = db_session.query(Users).first() # 第一条数据 print(res.id, res.name) #2 ausir # 存入了普通索引,在name里, 按首字母排序 #3 dragonfire #1 JWB
-
简单带条件的查询
res = db_session.query(Users).filter(Users.id < 3).all() res = db_session.query(Users).filter(Users.id < 3) # 不写all 就会查询出mysql语句 #SELECT users.id AS users_id, users.name AS users_name #FROM users #WHERE users.id < %(id_1)s # 但是循环依旧可以获得id ,和 name值 print(res) for u in res: print(u.id, u.name)
-
并列条件
res = db_session.query(Users).filter(Users.id < 3, Users.name == 'YWB').all() print(res) for u in res: print(u.id, u.name)
-
修改数据类型
# 先查后修改
db_session.query(Users).filter(Users.id == 2).update({'name': 'wusir', 'age': 333}) # 修改没有的会报错 sqlalchemy.exc.InvalidRequestError: Entity '<class 'create_table.Users'>' has no property 'age' db_session.query(Users).filter(Users.id == 2).update({'name': 'ausir'}) # 更新的sql语句 db_session.commit()
3. 一对多 创建 ForeignKey
-
引入外键和关系
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy.orm import relationship # 是个 函数 ,不是s 一个py文件 # ORM精髓所在 Model = declarative_base()
-
创建表
# 创建表 class Student(Model): # Users是对象 __tablename__ = 'student' # 映射到数据的表 id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32), index=True, nullable=False, unique=True) # 关联字段,让sch_id 与 shcool 的 id 进行关联,主外键关系(这里的ForeignKey一定要是表名.id不是对象名) sch_id = Column(Integer, ForeignKey('school.id')) # 多对一关系存储列 # 将student 与 school 创建关系 这个不是字段,只是关系,backref是反向关联的关键字 stu2sch = relationship('School', backref='sch2stu') # 这里是对象名 class School(Model): # Users是对象 __tablename__ = 'school' # 映射到数据的表 id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32), index=True, nullable=False, unique=True)
-
引擎更新
from sqlalchemy.engine import create_engine engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/sqlalchemy?charset=utf8") Model.metadata.create_all(engine)
外键
今日错误,School中间多加了个o,浪费了30分钟
4 curd foreign
-
不写对应外键的id,也可以加入进去,但是没有关联
-
复杂写法 添加
# 增加一条数据 # 优先增加school sc = School(name='EDUBeijing') db_session.add(sc) db_session.commit() # # 再添加student sch_fir = db_session.query(School).filter(School.name == 'EDUBeijing').first() stu = Student(name='DF', sch_id=sch_fir.id) # stu = Student(name='DF') # 不写对应外键的id, db_session.add(stu) db_session.commit()
-
添加数据 relationship 正向添加数据
stu = Student(name='DF',stu2sch=School(name='EDUBeijing')) db_session.add(stu) db_session.commit()
-
添加数据 relationship 反向添加数据
sch = School(name='EDUShanghai') sch.sch2stu = [ Student(name='haifeng'), Student(name='hai') ] db_session.add(sch) db_session.commit()
-
查询的 relationship 正向
res = db_session.query(Student).all() for stu in res: print(stu.id, stu.name,stu.stu2sch.name)
结果:
1 DF EDUBeijing 2 DF EDUBeijing 4 DF EDUBeijing 5 haifeng EDUShanghai 6 hai EDUShanghai
-
查询的 relationship 反向向
res = db_session.query(School).all()
for sch in res:
# print(len(sch.sch2stu), sch.name)
for stu in sch.sch2stu:
print(sch.name,stu.name)
结果
学生长度,学校
各个学生的名字, 所属学校
1对多时,外键写到多的那
5 添加多对多的表
-
创建表
class Girls(Model): # Users是对象 __tablename__ = 'girl' # 映射到数据的表 id = Column(Integer, primary_key=True ) # 主键 自增 name = Column(String(32), nullable=False) g2b = relationship('Boys', backref='b2g', secondary='hotel') # 这里是对象名 class Boys(Model): # Users是对象 __tablename__ = 'boy' # 映射到数据的表 id = Column(Integer, primary_key=True) # 主键 自增 name = Column(String(32), nullable=False) class Group(Model): # Users是对象 外键在这里 __tablename__ = 'group' # 映射到数据的表 id = Column(Integer, primary_key=True) boy_id = Column(Integer, ForeignKey("boy.id")) girl_id = Column(Integer, ForeignKey("girl.id"))
-
数据库添加情况
6 crud m2m
-
添加数据 之 relationship 正向添加数据
g = Girls(name='g1', g2b=[Boys(name='b1'), Boys(name='b2')]) db_session.add(g) db_session.commit()
-
添加数据 之 relationship 反向添加数据
b = Boys(name='B3') b.b2g = [ Girls(name="G2"), Girls(name="G3"), ] db_session.add(b) db_session.commit()
group 存的表关系
-
查询数据 之 relationship 正向
res = db_session.query(Girls).all() for g in res: for b in g.g2b: print(g.name, b.name)
-
查询数据 之 relationship 反向
res = db_session.query(Boys).all() for b in res : for g in b.b2g: print(b.name, g.name)
结果显示
... G2 B3 G3 B3 b1 g1 b2 g1 ...
写一个 app的flask-sqlalchemy
文件格式如下(像Django)
sql
app01
static
templates
views
user.py # 写数据库增删改查逻辑,通过flask路由前端操作 4
__init__.py # 写app,并把数据库的引擎等配置写入app 1
models.py # 写数据库表对象 3
manager.py # 执行app 2
-
执行manager程序
from app01 import create_app app = create_app() # 运行主程序 if __name__ == '__main__': app.run()
-
首先走_init_.py
from flask import Flask from app01.models import db from app01.views import user def create_app(): # 配置app,以及把数据库的引擎加入app , 给model使用 app = Flask(__name__) app.config['DEBUG'] = True app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123@127.0.0.1:3306/sqlalchemy?charset=utf8' app.config["SQLALCHEMY_POOL_SIZE"] = 50 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) # 初始化app app.register_blueprint(user.user_bp) return app
-
model.py里新建了数据库表 , 通过flask_sqlalchemy (封装了sqlalchemy的常用功能,更简洁)
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() # 封装了SQLALchemy class Users(db.Model): # 写对象(表) __tablename__ = 'users_flask' id = db.Column(db.Integer, primary_key=True) # db里都封装了(flask_sqlalchemy) name = db.Column(db.String(32), nullable=False) # db.Column 不像sqlalchemy都得导入 if __name__ == '__main__': from app01 import create_app app = create_app() db.create_all(app=app) #创建对象 = Model.metadata.create_all(engine)
-
此处写对表的增删改查逻辑,在视图里写
from flask import Blueprint from app01.models import Users, db # 传过Users表和 db数据库 user_bp = Blueprint('user_bp', __name__) # 增删改查逻辑 传参 #增 @user_bp.route('/add_user/<username>', methods=['POST', 'get']) def add_user(username): u = Users(name=username) db.session.add(u) db.session.commit() return '200ok i am user_bp' # 查 @user_bp.route('/get_user/<username>', methods=['POST', 'get']) def get_user(username): u = Users.query.filter(Users.name == username).first() return str(u.id)