草庐IT

django的update和create高级操作

骑台风走 2024-02-20 原文

0. 介绍

方法

get_or_create   

如果存在就返回,不存在就先创建再返回,返回值有两个,一个是操作的 model 实例,一个是是否是 cre    ated 的 布尔型数据update_or_create

select_for_update

一定要配合事务使用,会等待行锁释放之后,返回查询结果

bulk_create

批量创建

bulk_update

群更新

models.py

from django.db import models


# Create your models here.


class Text_one(models.Model):
    title = models.CharField(max_length=225)
    name = models.CharField(max_length=225, db_index=True)
    count = models.IntegerField(default=100)

get_or_create

介绍

这个函数的返回值有两个,一个是操作的 model 实例,一个是是否是 created 的 布尔型数据

参数defaults:model 除了name,这个字段,还有其他的字段,创建数据的时候,给不在查询条件内的字段,设置的默认值

注意: 查询的条件必须是唯一的,否则会造成多条数据返回而报错,这个逻辑同 get() 函数。

注意: 使用的字段,没有唯一的约束,并发的调用这个方法可能会导致多条相同的值插入。

示例

def t1(request):
    instance, create = models.Text_one.objects.get_or_create(name='天衣无缝1', defaults={
        'title': '天意'
    })
    print('instance', instance)
    print('create', create)
    # instance Text_one object (4)
    # create True
    return HttpResponse('ok')

update_or_create

介绍

存在的字段话,更新default字段内的内容·,不存在的话,就创建该数据。

示例

from django.shortcuts import render, HttpResponse

from . import models


def t1(request):
    instance, create = models.Text_one.objects.update_or_create(name='天衣无缝5', defaults={
        'title': '天意66',
    })
    print('instance', instance)
    print('create', create)
    return HttpResponse('ok')

select_for_update

事务操作

(22条消息) mysql在django中开启事务,实现悲观锁和乐观锁_骑台风走的博客-CSDN博客https://blog.csdn.net/qq_52385631/article/details/126899229?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126899229%22%2C%22source%22%3A%22qq_52385631%22%7D

介绍

1. 在django中使用,一定需要与事务连用,不然不起作用,作为悲观锁思想的排它锁实现方式,从粒度来看本质是行锁,用来解决mysql并发问题

2. 场景上,比如火车票订票,在屏幕上显示票量,而真正进行出票时,需要重新确定一下这个数据没有被其他客户端修改。所以,在这个确认过程中,可以使用for update。这是统一的解决方案方案问题,需要前期有所准备。

其他介绍:

1. 在我们的查询器上使用select_for_update来告诉数据库锁定对象,直到事务完成。
2. 在数据库中锁定一行需要一个数据库事务 - 我们使用Django的装饰器transaction.atomic来开启事务。

参数:

这个方法有两个默认参数,nowait=False 和 skip_locked=False

nowait=True的含义是匹配的记录被锁时不等待,直接抛异常。

skip_locked=True的含义是SELECT时跳过被锁的记录。

注意:MySQL版本要在8.0.1+ 以上才支持 nowait,skip_locked和of选项。

注意:在mysql加锁,依旧出现并发修改,原因如下:
1、必须置于事务中,事务要能生效,特别是spring中事务方法必须是public,且必须是由类外调用该事务方法。
2、for update的查询语句必须规范,要么查询条件是主键,要么查询条件要走索引,至于最终是锁行还是锁表都有可能。
3、如果有读写分离中间件,必须保证for update到主库,因为一般从库都是read-only( for update语句在read-only环境中会报错) 3. 线上环境均满足以上条件,且做测试发现能排它锁运行正常。最终找到原因为在线上分布式环境中开启了mybatis的二级缓存。

示例


from . import models
from django.db.models import Max, F
from time import sleep
from django.db import transaction


def t2(request):
    # 创建保存点
    # # 开启事务,当方法执行完以后,自动提交事务
    with transaction.atomic():
        sid = transaction.savepoint()
        try:
            # 锁住当前查询到的符合数据,锁住记录后其他的事务无法操作,等当前事务执行完,才允许别的事务进行操作
            instance = models.Text_one.objects.select_for_update().filter(id=1)
            print(instance)
            if instance.count() >= 100 or instance.count() < 150:
                models.Text_one.objects.filter(name='小宝').update(count=F('count') + 1)
        except Exception:
            print('ss')
            transaction.savepoint_rollback(sid)
    return HttpResponse('ok2')

bulk_create

介绍

1. 批量创建

2. 如果我们批量创建的数量过多,我们可以指定分批次来创建,通过 batch_size 参数来指定。

示例

from rest_framework.views import APIView
from rest_framework.response import Response
from . import models
 
# models
class UserInfo(models.Model):
    username = models.CharField(max_length=66)
 
# url
path('t3/', views.T3.as_view()),
 
# view
class T3(APIView):
    authentication_classes = []
 
    def get(self, request):
        userinfo_data = []
        for i in range(10):
            # 先生成对象
            user = models.UserInfo(username=i)
            print("user", user) # user UserInfo object
            userinfo_data.append(user)
        # 群增,分两次创建
        models.UserInfo.objects.bulk_create(userinfo_data,batch_size=2)
        return Response('ok')

bulk_update

介绍

1. 群修改

2. 需要注意的是 bulk_update 多了个参数,fields 这个是用来指定需要更新的字段。

3. 如我们下面所示,我们指定更新的是 name 字段,那么就算我们,更改了 title的数据,只要 fields 列表里没有指定该字段,那么数据库也不会更新该字段。

示例


from . import models


def t1(request):
    instance = models.Text_one.objects.all()
    for article in instance:
        article.name = "name_updated"
        article.title = "title_updated"
    models.Text_one.objects.bulk_update(instance, fields=['name'], batch_size=2)
    return HttpResponse('ok1')

其他

源码

# 源码
def select_for_update(self, nowait=False, skip_locked=False):
    """
    Returns a new QuerySet instance that will select objects with a
    FOR UPDATE lock.
    """
    if nowait and skip_locked:
        raise ValueError('The nowait option cannot be used with skip_locked.')
    obj = self._clone()
    obj._for_write = True
    obj.query.select_for_update = True
    obj.query.select_for_update_nowait = nowait
    obj.query.select_for_update_skip_locked = skip_locked
    return obj

参考文章

(2条消息) Django笔记十三之select_for_update等选择和更新等相关操作_vv安的浅唱的博客-CSDN博客_django select_for_updatehttps://blog.csdn.net/weixin_43354181/article/details/123697817(9条消息) Django中select_for_update方法的应用_˚天霸动霸Tua的博客-CSDN博客_django select_for_updatehttps://blog.csdn.net/kaikai0803/article/details/97278180
(12条消息) mysql开启事务和加锁(django)_骑台风走的博客-CSDN博客_django mysql事务https://blog.csdn.net/qq_52385631/article/details/122869771?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166332855416800182720785%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=166332855416800182720785&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-122869771-null-null.nonecase&utm_term=transaction.atomic&spm=1018.2226.3001.4450

 (12条消息) mysql开启事务和加锁(django)_骑台风走的博客-CSDN博客_django mysql事务https://blog.csdn.net/qq_52385631/article/details/122869771?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166332559116782427429565%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=166332559116782427429565&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-122869771-null-null.nonecase&utm_term=transaction.atomic%28%29&spm=1018.2226.3001.4450

(12条消息) 04、django高并发连接数据库的并发控制问题 和 简单代码测试_鞍-的博客-CSDN博客_django并发控制https://blog.csdn.net/weixin_41097516/article/details/113483346?utm_source=app&app_version=5.2.1&code=app_1562916241&uLinkId=usr1mkqgl919blen (14条消息) select...for update使用方法_鲨鱼辣椒灬的博客-CSDN博客_select…for updatehttps://blog.csdn.net/ll594317566/article/details/103869619

有关django的update和create高级操作的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  3. ruby - 导轨 4 : column reference "updated_at" is ambiguous with Postgres - 2

    我正在尝试使用“updated_at”字段的日期时间范围查询数据库。前端在JSON数组中发送查询:["2015-09-0100:00:00","2015-10-0223:00:00"]在RailsController中,我使用以下方法将两个字符串解析为DateTime:start_date=DateTime.parse(params[:date_range_arr][0])end_date=DateTime.parse(params[:date_range_arr][1])#...@events=@events.where('updated_atBETWEEN?AND?,start_d

  4. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  5. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  6. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  7. ruby-on-rails - ActiveRecord 的 find_or_create* 方法是否存在根本性缺陷? - 2

    有几种方法:first_or_create_by、find_or_create_by等,它们的工作原理是:与数据库对话以尝试找到我们想要的东西如果我们找不到,就自己做保存到数据库显然,并发调用这些方法可能会使两个线程都找不到它们想要的东西,并且在第3步中一个线程会意外失败。似乎更好的解决方案是,创建或查找即:提前在您的数据库中创建合理的唯一性约束。如果你想保存一些东西,就保存它如果有效,那就太好了。如果它因为RecordNotUnique异常而无法工作,它已经存在,太好了,加载它那么在什么情况下我想使用Rails内置的东西而不是我自己的(看起来更可靠)create_or_find?

  8. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

  9. ruby-on-rails - 如何让 Rails View 返回其关联的操作名称? - 2

    我有一个非常简单的Controller来管理我的Rails应用程序中的静态页面:classPagesController我怎样才能让View模板返回它自己的名字,这样我就可以做这样的事情:#pricing.html.erb#-->"Pricing"感谢您的帮助。 最佳答案 4.3RoutingParametersTheparamshashwillalwayscontainthe:controllerand:actionkeys,butyoushouldusethemethodscontroller_nameandaction_nam

  10. ruby-on-rails - 工厂女孩/Rails : Generator to create a factory for existing model? - 2

    我在我的Rails项目中使用rspec_rails和factory_girl_railsgem。所有模型都已创建。是否有我可以运行的生成器来为现有模型创建工厂文件?例如:我已经有了一个Blog模型。RSpec允许我通过简单地运行以下命令在spec/models/blog_spec.rb生成一个模型规范文件:railsgeneraterspec:modelblog是否有我可以在命令行中运行的生成器,它会为这个现有模型生成工厂文件,位于:spec/factories/blogs.rb?我在factory_girl_rails中没有看到任何关于发电机的提及文档。

随机推荐