使用documentation中的示例,我正在尝试将现有子项附加到新父项。首先,我尝试了这个例子:
>>> p = models.Parent()
>>> a1 = models.Association(extra_data='data1')
>>> a2 = models.Association(extra_data='data2')
>>> a1.child = models.Child()
>>> a2.child = models.Child()
>>> p.children.append(a1)
>>> p.children.append(a2)
>>> db.session.add(p)
>>> db.session.commit() # OK!
现在我的DB中有两个孩子和一个父母。然后我试了一下:
>>> p2 = models.Parent()
>>> a1 = models.Association(extra_data='data3')
>>> a2 = models.Association(extra_data='data4')
>>> a1.child = models.Child.query.get(1)
>>> a2.child = models.Child.query.get(2) # Oops!
Traceback (most recent call last):
File "<console>", line 1, in <module>
✂-----< ... >-------
File "/home/boss/codes/python_projects/c/flaskenv/lib/python3.5/site-packages/MySQLdb/connections.py", line 280, in query
_mysql.connection.query(self, query)
sqlalchemy.exc.IntegrityError: (raised as a result of Query-invoked
autoflush; consider using a session.no_autoflush block if this flush
is occurring prematurely) (_mysql_exceptions.IntegrityError) (1364,
"Field 'left_id' doesn't have a default value") [SQL: 'INSERT INTO
association (right_id, extra_data) VALUES (%s, %s)'] [parameters: (1,
'data3')]
# Let's continue
>>> db.session.rollback()
>>> a1.child
<app.models.Child object at 0x7f7bac39ffd0>
>>> a2.child
>>> a2.child = models.Child.query.get(2)
>>> a2.child
<app.models.Child object at 0x7f7bac2465c0>
>>> p2.children.append(a1)
>>> p2.children.append(a2)
>>> db.session.add(p2)
>>> db.session.commit() # OK!
>>>
我做错了什么?
注意:我没有使用自动提交,我已经管理了将子项附加到父项,并在session.rollback()
之后将它们添加到数据库中。
错误解释指出我“考虑使用session.no_autoflush块”,但是我需要更多地澄清这种机制是如何工作的,如果我禁用autoflush,它可能会导致另一个错误或安全威胁。
答案 0 :(得分:0)
好像我找到了一些解决方法:
使用session.no_autoflush(作为错误解释提供):
>>> p2 = models.Parent()
>>> a1 = models.Association(extra_data='data5')
>>> a2 = models.Association(extra_data='data6')
>>> with db.session.no_autoflush:
... a1.child = models.Child.query.get(1)
... a2.child = models.Child.query.get(2)
...
>>> p2.children.append(a1)
>>> p2.children.append(a2)
>>> db.session.add(p2)
>>> db.session.commit()
>>>
但是如果你不想厌倦冲洗东西,只需按照以下方式逐个追加孩子:
>>> p2 = models.Parent()
>>> a1 = models.Association(extra_data='data9')
>>> a2 = models.Association(extra_data='data10')
>>> a1.child = models.Child.query.get(1)
>>> p2.children.append(a1)
>>> a2.child = models.Child.query.get(2)
>>> p2.children.append(a2)
>>> db.session.add(p2)
>>> db.session.commit()
无论如何,我认为自动清除机制及其引起的错误仍需要更多解释。