flask-sqlalchemy中db.session.query和model.query方式要怎么选择

  1. 当插入一条新的记录时,使用db.session.commit()提交数据后,使用model.query()查不到新增加的数据
  2. db.session.commit()是提交了数据到数据库,但是没有刷新模型映射中的数据,也就是model.query()中的数据。而使用db.session.query()则是 从整个服务会话中进行查询,而db.session.commit()提交的数据在这里是有刷新的。

以上是我在网上找到的答案,当时也是遇到这个问题,增或者改数据后,直接model.query的结果时对时错,换成db.session这种模式就没问题了,我用的是flask-sqlalchemy库。

所以我有两个问题,第一个是导致这种情况发生的是如同上述吗?第二个,如果真的是存在这种情况,为什么很多教程包括辉大佬你的flask项目都还是model.query形式?

参考链接:

麻烦提供可以复现你说的问题的示例代码。

test2 里第二次查询赋值的变量是 books1,而你打印出来的是 books

以后麻烦用纯文本给出代码,你这样别人没法在本地运行测试。

class Book(PkModel):
    """books for a user."""

    __tablename__ = "books"
    name = Column(db.String(80), nullable=False)
    user_id = Column(db.Integer)

    def __init__(self, name, **kwargs):
        """Create instance."""
        super().__init__(name=name, **kwargs)

    def __repr__(self):
        """Represent instance as a unique string."""
        return f"<Book({self.name})>"


@blueprint.route("/test1/<name>", methods=["GET", "POST"])
def test1(name):

    db.session.add(Book(name=name))
    db.session.commit()

    print(f"新增book:{name}")

    return jsonify({"msg": "ok"})


@blueprint.route("/test2", methods=["GET", "POST"])
def test2():
    books = [i.name for i in Book.query.all()]
    print(f"第一次查询:{books}")
    time.sleep(10)
    books1 = [i.name for i in Book.query.all()]
    print(f"第二次查询:{books1}")

    return jsonify({"msg": "ok", "books": books, "book1": books1})

先请求一次test2 查询 ,然后再紧接着请求test1插入数据,发现test2请求的2次结果不变

OK,我晚点测试一下,以前没考虑过这个问题。

from sqlalchemy import create_engine
engine = create_engine("mysql://scott:tiger@hostname/dbname",
                                    encoding='utf-8', isolation_level='READ COMMITTED')

stackflow上有的回答是设置隔离级别为read-committed就可以,但是flask-sqlalchemy怎么设置隔离级别?我找不到这个方法或者参数。

使用 SQLALCHEMY_ENGINE_OPTIONS 配置,传递一个字典,键值匹配传入 create_engine 的参数。另外 SQLAlchemy 类也可以传递一个 engine_options 字典,作用相同,但是会覆盖对应配置的值。

请问有结果了吗

这是数据库隔离级别的问题,MySQL默认隔离级别是可重复读(REPEATABLE-READ),所以同一个事务里面前后查询结果是相同的;建议您第一次查询后显示提交或回滚事务,然后进行第二次查询。

借用你的图片

那怎么解决这个问题,sqlalchemy不能实时读取到最新的数据,手动设置隔离级别?

个人不建议手动改隔离级别,建议分多次请求查询,或者查询后显示提交事务吧。

那还是用model.query形式? 还是用db.session.query(model) ?

我比较喜欢用db.session.query :joy: