Flask-Sqlalchemy在插入多个实例时自动提交更新?

时间:2018-11-24 07:02:05

标签: python python-3.x flask sqlalchemy flask-sqlalchemy

我尝试用JSON编码的字符串保存一些列(例如,标签,模型)。

我希望始终保持解码状态。

我已经阅读了一些有关添加配置以禁用autocommit和autoflush的内容,但这是行不通的。

虽然实例已添加到db.session中,然后更改了值,但orm仍尝试执行UPDATE OPERATION,然后引发TypeError。

这是我的代码。

```python

import json
from sqlalchemy import orm
from flask_sqlalchemy import SQLAlchemy

session_options = dict(
    bind=None,
    autoflush=False,
    autocommit=False,
    expire_on_commit=False,
)
db = SQLAlchemy(session_options=session_options)


class Sample(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # tags, models : string of json.dumps(array)
    tags = db.Column(db.String(128), default='')
    models = db.Column(db.String(128), default='')

    def __init__(self, **kwargs):
        cls = self.__class__
        super(cls, self).__init__(**kwargs)
        self.formatting()

    @orm.reconstructor
    def init_on_load(self):
        self.formatting()

    def formatting(self):
        self.tags = json.loads(self.tags)
        self.models = json.loads(self.models)

    def save(self):
        self.tags = json.dumps(self.tags)
        self.models = json.dumps(self.models)

        db.session.add(self)
        db.session.commit()

        self.formatting()
        ## fixme !!!
        ## formatting after saved will cause auto-commit and raise TypeError 

```

谢谢:)

ps:Flask-SQLAlchemy == 2.3.2

1 个答案:

答案 0 :(得分:0)

此错误是由于在db.session.close()之后缺少db.session.commit()

引起的

有人告诉我db.session.close()是自动调用的。真正的人否认了我的认识。

然后我尝试引用sqlalchmey的源代码,然后发现db.session.commit()db.session而不是sqlalchemy.orm.scoping.scoped_session的实例。

这是sqlalchemy.orm.SessionTransaction

中的源代码

```python

sqlalchemy.orm.SessionTransaction

```

这真是令人困惑。


如果您想重复此错误,请参见以下测试代码:

```python

def commit(self):
    self._assert_active(prepared_ok=True)
    if self._state is not PREPARED:
        self._prepare_impl()

    if self._parent is None or self.nested:
        for t in set(self._connections.values()):
            t[1].commit()

        self._state = COMMITTED
        self.session.dispatch.after_commit(self.session)

        if self.session._enable_transaction_accounting:
            self._remove_snapshot()

    self.close()
    return self._parent

```

感谢您的阅读,希望消除您的困惑。