sam*_*ces 12 python django django-orm
Django ORM是否提供了有条件地创建对象的方法?
例如,假设您希望使用某种乐观并发控制来插入新对象.
在某个时刻,您知道要在该表中插入的最新对象,并且您只想在此后没有插入新对象时才创建新对象.
如果是更新,您可以根据修订号进行过滤:
updated = Account.objects.filter(
id=self.id,
version=self.version,
).update(
balance=balance + amount,
version=self.version + 1,
)
Run Code Online (Sandbox Code Playgroud)
但是,我找不到任何记录的方式来为a create()或save()call 提供条件.
我正在寻找在SQL查询级别应用这些条件的东西,以避免"读 - 修改 - 写"问题.
编辑:这不是一次Optimistic Lock尝试.这是OP提供的代码的直接答案.
Django提供了一种实现条件查询的方法.它还提供了以下update_or_create(defaults=None, **kwargs)快捷方式:
该
update_or_create方法尝试根据给定的数据从数据库中获取对象kwargs.如果找到匹配项,则会更新默认字典中传递的字段.默认值中的值可以是callables.
所以我们可以尝试混合和匹配这两个,以便重新创建提供的查询:
obj, created = Account.objects.update_or_create(
id=self.id,
version=self.version,
defaults={
balance: Case(
When(version=self.version, then=F('balance')+amount),
default=amount
),
version: Case(
When(version=self.version, then=F('version')+1),
default=self.version
)
}
)
Run Code Online (Sandbox Code Playgroud)
查询细分:
该update_or_create会尝试与检索对象id=self.id,并version=self.version在数据库中.
balance和version字段将相应地更新Case条件表达式中的值(请参阅答案的下一部分).id=self.id和version=self.version将要创建的对象,然后它将更新其字段balance和version字段.条件查询的细分:
balance 查询:
如果对象存在,则When表达式的条件为true,因此该balance字段将使用以下值更新:
# Existing balance # Added amount
F('balance') + amount
Run Code Online (Sandbox Code Playgroud)如果该对象被创建,它将接收作为初始balance的amount值.
version 查询:
如果对象存在,则When表达式的条件为true,因此该version字段将使用以下值更新:
# Existing version # Next Version
F('version') + 1
Run Code Online (Sandbox Code Playgroud)如果对象被创建,它将接收作为初始version的self.version值(它也可以是一个默认的初始版本等1.0.0).
笔记:
output_field参数Case,请查看此处.F()表达式是什么以及如何使用它的好奇心,我在这里有一个Q&A风格示例:如何在django中的模型字段之间执行算术运算| 归档时间: |
|
| 查看次数: |
791 次 |
| 最近记录: |