我有以下代码,我想做一个 upsert:
def add_electricity_reading(
*, period_usage, period_started_at, is_estimated, customer_pk
):
from sqlalchemy.dialects.postgresql import insert
values = dict(
customer_pk=customer_pk,
period_usage=period_usage,
period_started_at=period_started_at,
is_estimated=is_estimated,
)
insert_stmt = insert(ElectricityMeterReading).values(**values)
do_update_stmt = insert_stmt.on_conflict_do_update(
constraint=ElectricityMeterReading.__table_args__[0].name,
set_=dict(
period_usage=period_usage,
period_started_at=period_started_at,
is_estimated=is_estimated,
)
)
conn = DBSession.connection()
conn.execute(do_update_stmt)
return DBSession.query(ElectricityMeterReading).filter_by(**dict(
period_usage=period_usage,
period_started_at=period_started_at,
customer_pk=customer_pk,
is_estimated=is_estimated,
)).one()
def test_updates_existing_record_for_started_at_if_already_exists():
started_at = datetime.now(timezone.utc)
existing = add_electricity_reading(
period_usage=0.102,
customer_pk=customer.pk,
period_started_at=started_at,
is_estimated=True,
)
started_at = existing.period_started_at
reading = add_electricity_reading(
period_usage=0.200,
customer_pk=customer.pk,
period_started_at=started_at,
is_estimated=True,
)
# existing record was updated
assert reading.period_usage == 0.200
assert reading.id == existing.id
Run Code Online (Sandbox Code Playgroud)
在我的测试中,当我添加现有记录,period_usage=0.102然后再次执行查询但更改为period_usage=0.2. 当底部的最终查询返回记录时, period_usage 仍为 0.102。
知道为什么会发生这种情况吗?
“会话的作用是什么?”下的“会话基础知识”中对此行为进行了解释。会话保存对其已加载到称为标识映射的结构中的对象的引用,因此确保在会话生命周期内每个主键值一次仅存在 1 个唯一对象。您可以在自己的代码中使用以下断言来验证这一点:
assert existing is reading
Run Code Online (Sandbox Code Playgroud)
您正在执行的核心插入(或更新)语句不会像示例那样使会话与数据库中发生的更改保持同步Query.update()。为了获取新值,您可以使唯一对象的 ORM 加载状态过期:
DBSession.expire(existing) # or reading, does not matter
# existing record was updated
assert reading.period_usage == 0.200
assert reading.id == existing.id
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1590 次 |
| 最近记录: |