Flask框架中SQLAlchemy的使用方法

数据库配置文件(config.py

# config.py
USERNAME = "root"			# 数据库登录用户名	
PASSWORD = "123456"			# 数据库登录密码
HOST = "localhost"			# 数据库服务器地址,若为远程服务器填写对应的IP地址,这里是示例地址
PORT = "3306"				# 数据库连接端口号,MySQL默认常用端口是3306
DATABASE = "test_platform"	# 要访问的数据库名称

# 创建统一资源标识符(URI),用于指定数据库连接的详细信息
# SQLALCHEMY_DATABASE_URI的格式为:数据库类型 + 驱动://{登录名}:{密码}@{IP地址}:{端口号}/{数据库名}?charset={编码格式}
DB_URI = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOST}:{PORT}/{DATABASE}?charset=utf8'

# SQLALCHEMY_DATABASE_URI配置项,设置数据库的连接URI,让SQLAlchemy知道如何连接数据库
SQLALCHEMY_DATABASE_URI = DB_URI

# SQLALCHEMY_TRACK_MODIFICATIONS配置项,用于控制是否动态追踪对象修改情况
# 若设置为True,会追踪对象修改,但会消耗额外资源,默认不设置时会有告警提示,这里设为True开启追踪
SQLALCHEMY_TRACK_MODIFICATIONS = True

# SQLALCHEMY_ECHO配置项,用于设置是否在查询时显示原始的SQL语句
# 设为False表示不显示原始SQL语句,设为True则会在控制台等地方输出实际执行的SQL语句,方便调试查看
SQLALCHEMY_ECHO = False

Flask应用与SQLAlchemy初始化

创建Flask应用实例

在主应用文件(例如 app.py)中创建Flask应用实例,代码如下:

from flask import Flask

app = Flask(__name__)

导入配置数据

使用 app.config.from_pyfile() 方法从配置文件(config.py)导入配置信息到Flask应用实例中,示例代码:

from config import Config

app.config.from_pyfile(Config)

创建SQLAlchemy实例并关联应用(init_app 相关解释)

  • init_app 用法示例
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    db.init_app(app)
    return app
  • 为什么要用 init_app

在实际项目开发场景中,应用往往需要在不同的环境(如开发环境、测试环境、生产环境)下运行,而不同环境下的数据库配置通常是不一样的。

例如,开发环境下可能使用一个本地搭建的测试数据库,用户名、密码以及数据库名称等信息都是针对开发调试设置的;测试环境会使用专门的测试服务器上的数据库,有着独立的一套访问配置;生产环境更是有严格的线上数据库配置,涉及安全、性能等多方面考量。

通过 init_app 方法,我们可以先独立创建 SQLAlchemy 实例,之后根据具体的Flask应用在不同环境下的配置情况,再将二者关联起来。这样的方式使得数据库配置能够灵活切换,避免了把数据库配置固定写死在代码之中,极大地增强了代码的可维护性与扩展性,方便应对复杂多变的项目需求。

  • 可以不用 init_app

是可以的。如果项目相对简单,数据库配置固定不变,不存在要根据不同环境切换配置的情况,那么直接在创建 SQLAlchemy 实例时传入Flask应用实例进行初始化就可以了,如下所示:

from flask_sqlalchemy import SQLAlchemy
from flask import Flask

app = Flask(__name__)
# 直接通过app.config来配置SQLAlchemy相关的参数
app.config['SQLALCHEMY_DATABASE_URI'] ='sqlite:///example.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 直接传入app实例初始化,适合简单且配置固定的应用场景
db = SQLAlchemy(app)

不过对于大型、复杂的项目,尤其是那些需要频繁在不同环境间切换配置的项目,使用 init_app 会更加合适、便捷。

创建和删除表

创建表

在启动脚本(比如在 if __name__ == '__main__': 部分)按照以下方式创建表结构,这里涉及到 with app.app_context() 的使用:

if __name__ == '__main__':
    from app import app, db
    with app.app_context():
        db.create_all()
    app.run()

关于 with app.app_context() 的解释

Flask应用在运行时依赖应用上下文(app context)来管理和应用相关的各种状态以及配置信息。当执行 db.create_all() 操作时,它需要依据当前应用配置里通过 SQLALCHEMY_DATABASE_URI 配置项指定的数据库连接详情,再结合代码中定义的数据库模型类等相关信息,才能准确无误地在数据库中创建对应的表结构。

只有在这个应用上下文环境里,SQLAlchemy 才能获取到正确的配置信息,要是没有这个环境,比如直接从外部脚本运行相关代码时,SQLAlchemy 很可能无法获取到准确的配置内容,进而导致创建表的操作失败。

删除表

当需要删除表(注意,删除表操作会清除对应表中的所有数据,操作时要格外谨慎)时,同样需要在合适的脚本中使用 with app.app_context(),示例如下:

if __name__ == '__main__':
    from app import app, db
    with app.app_context():
        db.drop_all()
    app.run()

使用 with app.app_context() 的原因和创建表时一样,都是为了确保 db.drop_all() 操作能够依据当前Flask应用的配置准确地对数据库中的表进行删除操作,避免因获取不到正确配置而出现错误。

查询操作

查询所有记录

  • db 语句
results = db.session.query(YourModel).all()
  • sql 语句
SELECT * FROM your_table_name;

查询指定列记录

  • db 语句
results = db.session.query(YourModel.column1, YourModel.column2).all()
  • sql 语句
SELECT column1, column2 FROM your_table_name;

条件查询记录

  • db 语句
results = db.session.query(YourModel).filter(YourModel.column_name > value).all()
  • sql 语句
SELECT * FROM your_table_name WHERE column_name > value;

模糊查询记录(使用 LIKE

  • db 语句
results = db.session.query(YourModel).filter(YourModel.column_name.like('%keyword%')).all()
  • sql 语句
SELECT * FROM your_table_name WHERE column_name LIKE '%keyword%';

范围查询记录

  • 使用 BETWEEN... AND...
    • db 语句
results = db.session.query(YourModel).filter(YourModel.column_name.between(start_value, end_value)).all()
- **`sql` 语句**:
SELECT * FROM your_table_name WHERE column_name BETWEEN start_value AND end_value;
  • 使用 IN
    • db 语句
results = db.session.query(YourModel).filter(YourModel.column_name.in_(list_of_values)).all()
- **`sql` 语句**:
SELECT * FROM your_table_name WHERE column_name IN (value1, value2,...);

排序查询记录(使用 ORDER BY

  • db 语句
results = db.session.query(YourModel).order_by(YourModel.column_name.desc()).all()
  • sql 语句
SELECT * FROM your_table_name ORDER BY column_name DESC;

分组查询记录(使用 GROUP BYHAVING

  • db 语句
from sqlalchemy import func

results = db.session.query(YourModel.column_group, func.count(YourModel.id)).group_by(YourModel.column_group).having(func.count(YourModel.id) > some_value).all()
  • sql 语句
SELECT column_group, COUNT(id) FROM your_table_name GROUP BY column_group HAVING COUNT(id) > some_value;

多表关联查询记录(以简单的内连接为例)

假设有 ModelAModelB 两个模型类,通过 ModelA.idModelB.a_id 关联:

  • db 语句
results = db.session.query(ModelA.column1, ModelB.column2).join(ModelB).all()
  • sql 语句
SELECT ModelA.column1, ModelB.column2 FROM ModelA JOIN ModelB ON ModelA.id = ModelB.a_id;

子查询记录

  • db 语句
from sqlalchemy import select

subquery = db.session.query(func.avg(YourModel.column_name)).scalar_subquery()
results = db.session.query(YourModel).filter(YourModel.column_name > subquery).all()
  • sql 语句
SELECT * FROM your_table_name WHERE column_name > (SELECT AVG(column_name) FROM your_table_name);

去重查询记录(使用 DISTINCT

  • db 语句
results = db.session.query(YourModel.column_name).distinct().all()
  • sql 语句
SELECT DISTINCT column_name FROM your_table_name;

分页查询记录

  • db 语句
# limit 用于指定每页显示的记录数量,offset 用于设置偏移量,也就是从哪条记录开始查询
results = db.session.query(YourModel).limit(page_size).offset(page_number * page_size).all()
# paginate:进行分页操作,page参数指定页码,per_page参数指定每页显示的记录数。
results = db.session.query.paginate(page=page_number, per_page=page_size).all()
  • sql 语句
SELECT * FROM your_table_name LIMIT offset_value, page_size;

插入操作

插入单条记录

  • db 语句
new_record = YourModel(column1=value1, column2=value2)
db.session.add(new_record)
db.session.commit()
  • sql 语句
INSERT INTO your_table_name (column1, column2) VALUES (value1, value2);

插入多条记录

  • db 语句
records_to_add = [
    YourModel(column1=value1_1, column2=value2_1),
    YourModel(column1=value1_2, column2=value2_2)
]
db.session.add_all(records_to_add)
db.session.commit()
  • sql 语句
INSERT INTO your_table_name (column1, column2) VALUES (value1_1, value2_1), (value1_2, value2_2);

更新操作

更新单条记录

  • db 语句
record = db.session.query(YourModel).filter(YourModel.id == record_id).first()
if record:
    record.column_name = new_value
    db.session.commit()
  • sql 语句
UPDATE your_table_name SET column_name = new_value WHERE id = record_id;

更新多条记录(基于条件)

  • db 语句
db.session.query(YourModel).filter(YourModel.column_name == condition_value).update({YourModel.column_to_update: new_value})
db.session.commit()
  • sql 语句
UPDATE your_table_name SET column_to_update = new_value WHERE column_name = condition_value;

删除操作

删除单条记录

  • db 语句
record = db.session.query(YourModel).filter(YourModel.id == record_id).first()
if record:
    db.session.delete(record)
    db.session.commit()
  • sql 语句
DELETE FROM your_table_name WHERE id = record_id;

删除多条记录(基于条件)

  • db 语句
db.session.query(YourModel).filter(YourModel.column_name == condition_value).delete()
db.session.commit()
  • sql 语句
DELETE FROM your_table_name WHERE column_name = condition_value;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值