sqlalchemy及flask-sqlalchemy的使用方法
1.sqlalchemy
-
使用全面介绍(这种方法不推荐,推荐下边的一种方法)
from sqlalchemy import create_engine, Column, Integer, String, DateTime, MetaData, Table from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session from urllib.parse import quote_plus # 引入这个模块,解决数据库密码中存在@导致截断的问题,对密码进行编码。 raw_password = 'My@20241103' # 原始密码 # 对密码进行 URL 编码 encoded_password = quote_plus(raw_password) # 构造安全的连接字符串 connection_string = f"mysql+pymysql://root:{encoded_password}@localhost:3306/woniunote" # 1.连接数据库,建立连接引擎 engine = create_engine(connection_string, echo=False, pool_size=20) # echo为true会隐藏密码 # 2.定义数据模型(ORM) # 2-1第一种方法 # 定义表格数据对象的父类(里边含有表格的增删查改操作,是所有 ORM 映射类的基类) # Base = declarative_base() # 定义users表操作类,继承了orm基类 # 新建表的情况 # class Users(Base): # __tablename__ = 'users' # # # 如果需要在SQLAlchemy里面直接创建表结构,则详细定义表的列 # # 一般在可视化工具里边把数据表huo命令行客户端给建立好了,所以一般不在这个地方建立表的字段,所以下边的一般不用 # userid = Column(Integer, primary_key=True) # username = Column(String(50)) # password = Column(String(32)) # nickname = Column(String(30)) # qq = Column(String(15)) # role = Column(String(10)) # credit = Column(Integer) # createtime = Column(DateTime) # updatetime = Column(DateTime) # 创建表 # 在 SQLAlchemy 中,更推荐使用基类的元数据来创建所有表,而不是单个模型类 # Base.metadata.create_all(engine) # 更推荐上边这种创建表的方法,Base.metadata 是所有继承自基类的模型共享的元数据容器。显式使用 Base.metadata 表明您要创建所有模型对应的表。当添加新模型时,不需要修改创建表的代码 # Users.metadata.create_all(engine) 这种元数据建表不推荐,会被误解为只建立Users模型。 # 2-2 第二种方法 表已存在,反射已有表结构 # 自动反射现有数据库 metadata = MetaData() metadata.reflect(bind=engine) # 获取已存在的表 Base = declarative_base(metadata=metadata) # 直接使用反射的表,得到的是表对象模型 Users = metadata.tables['users'] Article = metadata.tables['article'] # 3.创建会话 Dbsession = sessionmaker(bind=engine) # 绑定连接引擎,引入会话类 # dbsession=Dbsession() #1.创建会话实例 dbsession = scoped_session(Dbsession) # 1.创建线程安全的会话实例,多线程环境中,强烈建议使用 scoped_session。 # 上述请求结束时需要清理(Web框架通常自动处理)dbsession.remove() # 关闭并重置当前线程的Session.flask中在app.teardown_appcontext钩子中使用这句话销毁这个会话 # 4.执行操作 if __name__ == '__main__': # result = dbsession.query(Article).all() result = dbsession.query(Users).all() print(result)
-
推荐使用的方法
# -*- coding: utf-8 -*-
# --------------------------------------
# 利用SQLAlchemy实现数据库orm(对象关系映射),简化数据库的操作
from sqlalchemy import create_engine, Column, Integer, String, DateTime, MetaData, Table
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import declarative_base, sessionmaker, scoped_session
from urllib.parse import quote_plus # 引入这个模块,解决数据库密码中存在@导致截断的问题,对密码进行编码。
raw_password = 'My@20241103' # 原始密码
# 对密码进行 URL 编码
encoded_password = quote_plus(raw_password)
# 构造安全的连接字符串
connection_string = f"mysql+pymysql://root:{encoded_password}@localhost:3306/woniunote"
# 1.连接数据库,建立连接引擎
engine = create_engine(connection_string, echo=False, pool_size=20) # echo为true会隐藏密码
# 2.定义数据模型(ORM)
# 自动映射整个数据库
Base = automap_base()
Base.prepare(autoload_with=engine)
# # 获取映射的类,得到的是表对象映射模型 最后一个users和article是表名
Users = Base.classes.users
Article = Base.classes.article
# 3.创建会话
Dbsession = sessionmaker(bind=engine) # 绑定连接引擎,引入会话类
# dbsession=Dbsession() #1.创建会话实例
dbsession = scoped_session(Dbsession) # 1.创建线程安全的会话实例,多线程环境中,强烈建议使用 scoped_session。
# 上述请求结束时需要清理(Web框架通常自动处理)dbsession.remove() # 关闭并重置当前线程的Session.flask中在app.teardown_appcontext钩子中使用这句话销毁这个会话
# 4.执行操作
if __name__ == '__main__':
# 1.查询第一个或全部
# result = dbsession.query(Article).first()
result = dbsession.query(Users).all()
print(result[0].nickname)
# 2.条件查询
result = dbsession.query(Users).filter_by(username="admin").first()
print(result.nickname)
result = dbsession.query(Users).filter(Users.nickname.like("%浪浪山%")).all()
print(result[0].username)
result = dbsession.query(Users).filter(Users.userid > 1).all()
print(result[0].username)
# 3.获取特定列
names = dbsession.query(Users.username).all()
names2 = dbsession.query(Users.userid,Users.username).all()
print(names2)
# 4.多条件查询
results = dbsession.query(Users).filter(
Users.username != "Alice",
Users.nickname.contains("浪浪山")
).order_by(Users.userid.desc()).limit(10).all()
print(results)
# 5.新增插入
new_user = Users(username="Alice", password='234567', role="user")
dbsession.add(new_user)
dbsession.commit() # 提交事务
# 6.批量插入
dbsession.add_all([
Users(username="Bob", password='1234566', role="user"),
Users(username="Charlie", password='123456', role="user")
])
dbsession.commit()
# 7. 删除和更新
row = dbsession.query(Users).filter_by(username="Ali").first()
row.password = '666666'
dbsession.commit()
# 删除
dbsession.query(Users).filter_by(username="Alice").delete()
dbsession.commit()
2.flask-sqlalchemy
project/
├── app/
│ ├── __init__.py # 工厂函数
│ ├── extensions.py # 扩展实例
│ ├── models/ # 模型目录
│ ├── routes/ # 视图蓝图
│ └── templates/
├── migrations/ # 数据库迁移
└── config.py # 配置文件
三步:创建db实例;创建模型类和操作方法;生成一个访问接口(通过路由获取这个数据表的值)
实现方式
- 创建数据库实例文件 (extensions.py)
# extensions.py
from flask_sqlalchemy import SQLAlchemy
# 创建未初始化的SQLAlchemy实例
db = SQLAlchemy()
- 模型定义文件 (models.py)
# models.py
from .extensions import db
class User(db.Model): #(底下的字段文件通过sqlacodegen模块来生成,见底下)
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
- 应用初始化文件 (app.py)
# app.py
from flask import Flask
from .extensions import db
from . import models # 确保模型被导入
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'f"mysql+pymysql://root:My%4020241103@localhost:3306/woniunote"'
# 初始化数据库
db.init_app(app)
return app
if __name__ == '__main__':
app = create_app()
app.run(debug=True)
- 在其他文件中使用数据库
# routes.py
from flask import Blueprint, jsonify
from .extensions import db
from .models import User
api = Blueprint('api', __name__)
@api.route('/users')
def get_users():
users = User.query.all()
return jsonify([{'id': u.id, 'username': u.username} for u in users])
@api.route('/add-user/<name>')
def add_user(name):
new_user = User(username=name, email=f"{name}@example.com")
db.session.add(new_user)
db.session.commit()
return f"Added user {name}!"
关键点说明
-
跨文件使用:
-
任何需要操作数据库的文件只需:
from .extensions import db from .models import User # 或其他模型
-
💎使用sqlacodegen获取模型实例:(自动生成表模型文件)
Terminal里输入命令:
sqlacodegen mysql+pymysql://root:My%4020241103@localhost/woniunote --tables users,article > models.py
调整模型文件models.py(替换 Base
为 db.Model
):
一个生成的例子(这个文件的表模型还可以封装其他方法):
# 数据库表模型 sqlacodegen mysql+pymysql://root:My%4020241103@localhost/woniunote --tables users,article > model.py 获取表模型
import datetime
from typing import Optional
from sqlalchemy import Integer, String, text, DateTime
from sqlalchemy.orm import Mapped, mapped_column
from woniu_note.extensions import db
class Users(db.Model):
__tablename__ = 'users'
userid: Mapped[int] = mapped_column(Integer, primary_key=True)
username: Mapped[str] = mapped_column(String(50))
password: Mapped[str] = mapped_column(String(32))
role: Mapped[str] = mapped_column(String(10), server_default=text("'user'"))
credit: Mapped[int] = mapped_column(Integer, server_default=text("'50'"))
nickname: Mapped[Optional[str]] = mapped_column(String(30))
avatar: Mapped[Optional[str]] = mapped_column(String(20))
qq: Mapped[Optional[str]] = mapped_column(String(15))
createtime: Mapped[Optional[datetime.datetime]] = mapped_column(DateTime)
updatetime: Mapped[Optional[datetime.datetime]] = mapped_column(DateTime)
# 这里边还可以封装其他方法如:
# def find_user_by_id(self, userid):
# row = db.session.query(Users).filter(Users.userid == userid).first()
# return row