我一直在尝试使用SQLAlchemy ORM的bulk_update_mappings
方法,但我收到了一条最无用的错误消息:
Traceback (most recent call last):
File "/vagrant/strategies/tests/test_collectors.py", line 173, in test_collect__with_update
provider.collect()
File "/vagrant/strategies/models.py", line 46, in collect
self.collector.update()
File "/vagrant/strategies/database/collectors.py", line 60, in update
db_session.bulk_save_objects(strategies)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/orm/scoping.py", line 150, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2203, in bulk_save_objects
return_defaults, update_changed_only)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2340, in _bulk_save_mappings
transaction.rollback(_capture_exception=True)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 182, in reraise
raise value
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/orm/session.py", line 2332, in _bulk_save_mappings
isstates, update_changed_only)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 121, in _bulk_update
bookkeeping=False)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 705, in _emit_update_statements
value_params)
File "/usr/local/miniconda3/lib/python3.4/site-packages/sqlalchemy/orm/persistence.py", line 998, in _postfetch
state._expire_attributes(state.dict,
AttributeError: 'NoneType' object has no attribute '_expire_attributes'
当我使用bulk_save_objects
时也会发生同样的错误,但奇怪的是bulk_insert_mappings
上没有,这似乎表明我的更新存在一些问题,但文档不是很有帮助。我的猜测是它与人际关系有关,但我尝试使用完整的关系对象和他们的id
来获取更新值,到目前为止还没有运气。
任何想法都将不胜感激!
答案 0 :(得分:-1)
因此,我发现bulk_save_objects
与其他一些ORM功能(load_only
)不兼容。这是导致问题的代码的一部分:
new_data_dict = get_me_the_data_blah_blah()
existing = db_session.query(Stuff).filter_by(visible=True).options(load_only('id', 'some_unique_field'))
# THIS: ^^^^^^^^^
existing = {s.some_unique_field: s for s in existing.all()}
new = []
for d in new_data_dict:
item = existing.get(d['some_unique_field'])
if item is not None:
for field, value in d.items():
setattr(item, field, value)
else:
item = Strategy(provider=self.provider, **d)
new.append(item)
db_session.bulk_save_objects(new)
db_session.commit()
因此,对于load_only
(原始实现仍然使用Session.add_all
),某些值从未被引用,因此从未加载,因此批量方法将它们视为{{1} }。
因此,删除None
可解决问题:
load_only