- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
本篇笔记将介绍 update 和 create 的一些其他用法,目录如下:
前面我们介绍过 get() 和 create() 的用法,那么 get_or_create() 的意思很简单,就是 获取或者创建,如果 存在就返回,不存在就先创建再返回 .
假设对于 Blog model,我们想看下数据库有没有 name="hunter", tagline="tagline_test" 的数据,没有的话创建并获取这条数据,有的话,就直接获取.
在之前我们操作可能是:
try:
blog = Blog.objects.get(name='hunter', tagline='tagline_test')
except Blog.DoesNotExist:
blog = Blog(name='hunter', tagline='tagline_test')
blog.save()
现在我们可以直接这样操作:
blog, created = Blog.objects.get_or_create(name='hunter', tagline='tagline_test')
这个函数的返回值有两个,一个是操作的 model 实例,一个是是否是 created 的 布尔型数据.
created 为 True,表示这条数据是创建,create() 到的 created 为 False,表示这条数据是获取, get() 到的 。
注意: 查询的条件必须是 唯一 的,否则会造成多条数据返回而报错,这个逻辑同 get() 函数.
注意: 使用的字段,没有唯一的约束,并发的调用这个方法可能会导致多条相同的值插入.
字段默认值 。
假设 Blog 这个 model 除了 name, tagline 这两个字段外,还有 field_1 和 field_2 字段,但是他们不在我们查询的条件内,作用为在创建的时候设置的默认值,我们可以通过 defaults 来操作:
blog, created = Blog.objects.get_or_create(
name='hunter',
tagline='tagline_test',
defaults={
'field_1': 'field_1_value',
'field_2': 'field_2_value'
}
)
最后关于这个函数,有个小提示,如果这个函数用在接口里,那么根据 幂等性 ,我们应该使用 POST 方法来请求,而不是 GET 请求.
关于幂等性的概念,有兴趣的话可以去查询一下.
更新或者创建,使用方法同 get_or_create() 。
假设对于 Blog model 我们想实现的操作如果存在 name='hunter', tagline='tagline_test' 的数据就将其 field_1 和 field_2 的字段更新,不存在的话,就创建该数据.
之前的操作逻辑大概如下:
defaults = {"field_1": "field_1_value", "field_2": "field_2_value"}
try:
obj = Blog.objects.get(name='hunter', tagline='tagline_test')
for key, value in defaults.items():
setattr(obj, key, value)
obj.save()
except:
new_values = {"name": "hunter", "tagline": "tagline_test}
new_values.update(defaults)
obj = Blog(**new_values)
obj.save()
现在我们使用 update_or_create 可以如下操作:
obj, created = Blog.objects.update_or_create(
name='hunter', tagline='tagline_test',
defaults={"field_1": "field_1_value", "field_2": "field_2_value"}
)
select_for_update 的操作复杂一点,作用类似于 SQL 中的 SELECT ... FOR UPDATE 语句 。
操作如下:
from django.db import transaction
blog_list = Blog.objects.select_for_update().filter(name="hunter")
with transaction.atomic():
for blog in blog_list:
...
当 blog_list 去获取数据的时候,所有匹配上的 entries 都会被锁,直到这个事务结束.
意味着这个时候,其他的事务会被阻止更改或者重新在这些数据上加锁.
我们来举个例子,在我们执行下面的语句时:
import time
from django.db import transaction
blog_list = Blog.objects.select_for_update().filter(name="hunter")
with transaction.atomic():
for blog in blog_list:
print("locking ...")
time.sleep(20)
这个时候,我们在重新开一个 shell,来执行下面的语句:
Blog.objects.filter(name="hunter").update(name="hunter_1")
因为第一个 shell 里执行的命令还没有结束,而且在数据上加了锁,因此第二个 shell 里的语句会进入等待,直到第一个 shell 里的命令执行完成之后,第二个 shell 里的命令才会执行.
注意: 如果在第一个命令里,对 blog 数据进行操作,比如 把 name 字段改为了 hunter_2,那么在第二条命令的条件里筛选不到结果然后更新的.
批量创建,在前面介绍增删改查的时候介绍过一次,这里再简单做一下示例:
from blog.models import Blog
blog_list = [
Blog(name="hunter_1", tagline="tag_1"),
Blog(name="hunter_2", tagline="tag_2"),
Blog(name="hunter_3", tagline="tag_3"),
Blog(name="hunter_4", tagline="tag_4")
]
Blog.objects.bulk_create(blog_list)
如果我们批量创建的数量过多,我们可以指定分批次来创建,通过 batch_size 参数来指定.
Blog.objects.bulk_create(blog_list, batch_size=2)
批量更新,方式与 bulk_create 的方式类似,以下是使用示例:
blog_list = Blog.objects.filter(id__lte=20)
for blog in blog_list:
blog.name = "name_updated"
blog.tagline = "tag_updated"
Blog.objects.bulk_update(blog_list, fields=['name'], batch_size=2)
需要注意的是 bulk_update 多了个参数,fields 这个是用来指定需要更新的字段.
如我们上面的命令所示,我们指定更新的是 name 字段,那么就算我们更改了 tagline 的数据,只要 fields 列表里没有指定该字段,那么后台也不会更新该字段.
以上就是本篇笔记全部内容,接下来我们将介绍一下查询中的其他用法,比如latest,first,contains 等.
本文首发于本人微信公众号:Hunter后端 。
原文链接: Django笔记十三之select_for_update等选择和更新等相关操作 。
如果想获取更多相关文章,可扫码关注阅读:
最后此篇关于Django笔记十三之select_for_update等选择和更新等相关操作的文章就讲到这里了,如果你想了解更多关于Django笔记十三之select_for_update等选择和更新等相关操作的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我想创建一个模型,其 ID 等于该模型当前最大 ID 加一(如自动增量)。我正在考虑使用 select_for_update 执行此操作,以确保当前最大 ID 不存在竞争条件,如下所示: with t
我用过 select_for_update()很多。但是,在我使用过的所有情况下,它都是通过这样的经理来完成的: with transaction.atomic(): transaction
我正在做一个类似于电子商务的项目,在这个项目中,我有一些模型来表示存储中有一定数量的产品,用户可以购买一定数量的产品,只要它不超过存储的数量.我想避免在服务器收到多个购买同一产品的请求时发生竞争条件。
Django documentation指出: If you were relying on “automatic transactions” to provide locking between s
select_for_update 的 Django 文档说 Using select_for_update() on backends which do not support SELECT ...
我有一个代码,应该可以在并发请求和高负载下工作。 我写了一个例子来更好地理解我正在尝试做的事情: def add_tag(): with transaction.atomic():
我有一行整数值,该行有很多并发请求,我希望每次读取操作后都进行更新操作(增量),并保持数据一致,只能一个请求读取->同时更新。 我做了一些研究并弄清楚了 select_for_update(),我还想
我有一些代码,如果嵌套调用 select_for_update() 会简单很多,但恐怕我自己陷入了僵局。 例子: with transaction.atomic(): uu1 = UniUse
我知道如果我们有多个并发用户, select_for_update 会锁定正在查询的记录。但它是否也会影响对查询记录的评估。 例如,如果用户 A 和用户 B 基于一个 bool 变量 'Availab
我有一个由 MySQL 数据库支持的 Django 应用程序。我最近将一段代码从请求流中移出并放入了一个流程中。该代码使用 select_for_update() 锁定数据库中受影响的行,但现在我偶尔
代码崩溃 @transaction.atomic def cancel_one(o_id): order= Order.objects.select_for_update().get(id=o
如果我执行 select_for_update,该锁何时/如何释放?一些示例代码: for rec_id in list(1,2,3): record = MyModel.objects.se
有谁知道您是否可以在单个查询中同时执行 .select_for_update() 和 .select_related() 语句?如: employee = get_object_or_404(Empl
我在一个大型项目中使用 django。 我从模型的 save 内部调用 celery task,该模型调用一个方法,该方法在循环中调用另一个方法。即: celery task --> function
Django documentation州 If you were relying on “automatic transactions” to provide locking between sel
正如 Django 文档所说,select_for_update返回一个 Queryset。但是 get 没有。现在我有一个查询,我确信它只会返回一个元组。但我还需要为此事务获取锁。所以我正在做类似的
我遇到了一个奇怪的情况,当在 transaction.atomic() block 中使用 select_for_update() 时,Django 和 Postgres 中记录的查询顺序不同。 基本
我有类似的东西: newsletter = Newsletter.select_for_update().latest() newsletter.started_sending = timezone.
我有一个如下表: SELECT id, name FROM node; +----+------+ | id | name | +----+------+ | 5 | na | +----+--
我是一名优秀的程序员,十分优秀!