本篇笔记将介绍 update 和 create 的一些其他用法,目录如下:

  1. get_or_create
  2. update_or_create
  3. select_for_update
  4. bulk_create
  5. 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 等。

本文首发于本人微信公众号:Hunter后端

原文链接:Django笔记十三之select_for_update等选择和更新等相关操作

如果想获取更多相关文章,可扫码关注阅读:

Django笔记十三之select_for_update等选择和更新等相关操作的更多相关文章

  1. python 学习笔记_1 pip安装、卸载、更新包相关操作及数据类型学习

    '''prepare_1 pip安装.卸载.更新组件type 各数据类型''' py -3 -m pip py -3 -m pip listpy -3 -m pip show nosepy -3 -m ...

  2. 6月20日 Django中ORM介绍和字段、字段参数、相关操作

    一.Django中ORM介绍和字段及字段参数 二.Django ORM 常用字段和参数 三.Django ORM执行原生SQL.在Python脚本中调用Django环境.Django终端打印SQL语句 ...

  3. 《C++游戏开发》笔记十三 平滑过渡的战争迷雾(一) 原理:Warcraft3地形拼接算法

    本系列文章由七十一雾央编写,转载请注明出处.  http://blog.csdn.net/u011371356/article/details/9611887 作者:七十一雾央 新浪微博:http:/ ...

  4. Django笔记 —— Admin(Django站点管理界面)

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  5. Django笔记 —— 模型

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  6. python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容

    python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...

  7. java之jvm学习笔记十三(jvm基本结构)

    java之jvm学习笔记十三(jvm基本结构) 这一节,主要来学习jvm的基本结构,也就是概述.说是概述,内容很多,而且概念量也很大,不过关于概念方面,你不用担心,我完全有信心,让概念在你的脑子里变成 ...

  8. Web框架——Django笔记

    Web框架--Django笔记 MVC和MTV MVC:Model.View.Controller MTV:Model.Template.View Django--MTV 1.创建Django程序   ...

  9. Go语言学习笔记十三: Map集合

    Go语言学习笔记十三: Map集合 Map在每种语言中基本都有,Java中是属于集合类Map,其包括HashMap, TreeMap等.而Python语言直接就属于一种类型,写法上比Java还简单. ...

  10. struts2官方 中文教程 系列十三:利用通配符选择方法

    介绍 在本教程中,我们将介绍如何在struts.xml中配置action节点以达到仅使用一个action节点将几个不同的url关联到特定action类的特定方法.这样做的目的是减少struts.xml ...

随机推荐

  1. PostgreSQL 存储过程 通过设定条件,返回指定的数据表记录

    PL/pgSQL是 PostgreSQL 数据库系统的一个可装载的过程语言. PL/pgSQL的设计目标是创建一种可装载的过程语言,可以可用于创建函数和触发器过程, 在SQL语言中添加控制结构功能, ...

  2. oracle 存过调试 stepinto stepover stepout

    step into:单步执行,遇到子函数就进入并且继续单步执行(简而言之,进入子函数): step over:在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止, ...

  3. CentOS 8.x 编译安装LNMP(Linux + Nginx + MySQL + PHP)架构部署动态网站环境

    LNMP动态网站部署架构是一套由Linux + Nginx + MySQL + PHP组成的动态网站系统解决方案,具有免费.高效.扩展性强且资源消耗低等优良特性,目前正在被广泛使用. 前传: 1.Ce ...

  4. vue富文本(5版本)组件

    <template> <div> <div style="border: 1px solid #ccc; width: 500px"> < ...

  5. swoft-个基于 Swoole 原生协程的PHP 微服务框架

    刚才百度了一下swoft框架,官网打不开了,仓库也暂停了.不由感慨.曾经和同事踩了许多坑使用此极其小众的框架完成微服务项目.使用它的唯一目的就是提高程序性能(底层使用了协程),为此大家都学习了很多新知 ...

  6. 简单了解promise

    promise是什么: JavaScript中存在很多异步操作, Promise将异步操作队列化,按照期望的顺序执行,返回 符合预期的结果.可以通过链式调用多个 Promise达到我们的目的. Pro ...

  7. 移动服务(f[i] [j] [k],这三个人,位置为a[i],j,k的最小价值)

    移动服务(f[i] [j] [k],这三个人,位置为a[i],j,k的最小价值) 题意 给出点之间到达价值,使用3个人处理一个序列,f[i] [j] [k],这三个人,每次处理序列中一个值,三个人中一 ...

  8. Ubuntu与centos之间的文件传输

          Ubuntu与centos之间的文件传输 默认端口:22 传输前确认端口是否开启 1.在Ubuntu上安装scp命令 apt-get install openssh-server 2.将U ...

  9. MyBatis-Plus使用SQL语句

    项目中碰到一个必须要使用动态SQL的地方, 想着在xml文件中进行一层一层的判断太麻烦了,也不好理解,要是能在Java代码中组织好SQL,进行查询操作 QueryWrapper<object&g ...

  10. 华为ME60 配置PPPOE-radius 业务

    华为ME60 配置PPPOE-radius 业务 1.创建radius 认证 # radius-server source interface LoopBack0 radius-server grou ...