本篇笔记将介绍 update 和 create 的一些其余用法,目录如下:
- get_or_create
- update_or_create
- select_for_update
- bulk_create
- bulk_update
1、get_or_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 申请。
对于幂等性的概念,有趣味的话能够去查问一下。
2、update_or_create
更新或者创立,应用办法同 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"}
)
3、select_for_update
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,那么在第二条命令的条件里筛选不到后果而后更新的。
4、bulk_create
批量创立,在后面介绍增删改查的时候介绍过一次,这里再简略做一下示例:
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)
5、bulk_update
批量更新,形式与 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 等。
本文首发于自己微信公众号:Django 笔记。
原文链接:Django 笔记十三之 select_for_update 等抉择和更新等相干操作
如果想获取更多相干文章,可扫码关注浏览: