【问题标题】:Sqlalchemy with Flask - deleted data is still shown带有 Flask 的 Sqlalchemy - 仍显示已删除的数据
【发布时间】:2018-01-30 10:55:09
【问题描述】:

说明

我有一个带有原始 SQLalchemy 的 Flask 应用程序。应用程序旨在在公司内部使用,以便更轻松地使用 MySQL 保存测量数据

在一个页面上,我有一个表格,其中包含用于测量的所有设备和一个用于添加、删除或修改测量设备的表单。

问题

问题是当我在数据库中输入新设备时,页面会自动刷新以从数据库中获取新数据,有时会显示新设备,有时刷新页面时不会显示。换句话说,即使该行在数据库中可见,表中添加的行也会出现和消失。当我尝试从数据库中删除设备时也是如此。有时会显示该行,但有时在刷新从数据库中删除行的页面时不会显示该行。 与此类似的所有示例(添加、删除和修改数据)都会出现相同的问题。

我尝试过的

下面是表格模型的代码:

class DvDevice(Base):
    __tablename__ = "dvdevice"

    id = Column("device_id", Integer, primary_key=True, autoincrement=True)
    name = Column("device_name", String(50), nullable=True)
    code = Column("device_code", String(10), nullable=True, unique=True)
    hw_ver = Column("hw_ver", String(10), nullable=True)
    fw_ver = Column("fw_ver", String(10), nullable=True)
    sw_ver = Column("sw_ver", String(10), nullable=True)

这是从表中插入/删除数据的代码。

    #Insertion
    device = DvDevice()
    device.code = self.device_code
    device.name = self.device_name
    device.hw_ver = self.hw_ver
    device.fw_ver = self.fw_ver
    device.sw_ver = self.sw_ver
    ses.add(device)
    ses.commit()
    ses.expire_all() #Should this be here?

    # Deletion
    ses.query(DvDevice).filter_by(id=self.device_id).delete()
    ses.commit()
    ses.expire_all() # Should this be here?

我已阅读堆栈上的一些帖子,在 models.py 中包含以下装饰器函数

@app.teardown_appcontext
def shutdown_session(exception=None):
   ses.expire_all() #ses being database session object.

我试过了,但它仍然不能正常工作。我应该把装饰器功能放在其他地方吗?

我尝试的第二件事是在所有提交之后放置ses.expire_all(),但它仍然不起作用。

我应该怎么做才能防止这种情况发生?

编辑 1

from sqlalchemy import create_engine, update
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool

from config import MYSQLCONNECT

engine = create_engine(MYSQLCONNECT)
Session = sessionmaker(bind=engine)

session = Session()

【问题讨论】:

  • 请说明ses 的定义方式。它是一个范围会话吗? ses.expire_all() 在拆卸期间是不够的,尤其是对于 MySQL,因为 MySQL 的默认事务隔离级别是 REPEATABLE READ。如果您的事务从一个请求到另一个请求继续进行,您会发现某些请求可能会看到其他请求看不到的数据,反之亦然。所以:始终以请求处理开始和结束您的事务,而不仅仅是在您进行更改时。
  • 我更新了问题。我不完全理解“始终通过请求处理开始和结束您的事务,而不仅仅是在您进行更改时”。
  • 在拆卸期间始终提交或回滚,可能关闭/删除会话(以便将连接返回到池)。如果您的编辑就是您所拥有的,并且您正在使用线程服务器来处理请求,那么您也会遇到一组不同的问题。 Session 不是线程安全的。
  • 所以我应该在每次请求后关闭会话并在下次再次提交之前启动另一个会话?服务器有 2 个网络工作者。就像我说的,它将在一台或两台计算机上内部运行。这会是个问题吗?
  • 好读:"When do I construct a Session, when do I commit it, and when do I close it?""Is the session thread-safe?"。我不完全确定您所说的“网络工作者”是什么意思,所以后者可能适用也可能不适用。

标签: python mysql flask sqlalchemy


【解决方案1】:

我使用http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#when-do-i-construct-a-session-when-do-i-commit-it-and-when-do-i-close-it中的以下函数解决了这个问题:

from contextlib import contextmanager

@contextmanager
def session_scope():
    """Provide a transactional scope around a series of operations."""
    session = Session()
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()



with session_scope() as session:
    ... # code that uses session

问题是我在开始时创建了会话对象,然后从未关闭它。

【讨论】:

    猜你喜欢
    • 2020-12-02
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 2015-10-22
    • 1970-01-01
    • 2017-09-20
    相关资源
    最近更新 更多