码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • django的update和create高级操作


    0. 介绍

    方法

    get_or_create   

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

    select_for_update

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

    bulk_create

    批量创建

    bulk_update

    群更新

    models.py

    1. from django.db import models
    2. # Create your models here.
    3. class Text_one(models.Model):
    4. title = models.CharField(max_length=225)
    5. name = models.CharField(max_length=225, db_index=True)
    6. count = models.IntegerField(default=100)

    get_or_create

    介绍

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

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

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

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

    示例

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

    update_or_create

    介绍

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

    示例

    1. from django.shortcuts import render, HttpResponse
    2. from . import models
    3. def t1(request):
    4. instance, create = models.Text_one.objects.update_or_create(name='天衣无缝5', defaults={
    5. 'title': '天意66',
    6. })
    7. print('instance', instance)
    8. print('create', create)
    9. 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的二级缓存。

    示例

    1. from . import models
    2. from django.db.models import Max, F
    3. from time import sleep
    4. from django.db import transaction
    5. def t2(request):
    6. # 创建保存点
    7. # # 开启事务,当方法执行完以后,自动提交事务
    8. with transaction.atomic():
    9. sid = transaction.savepoint()
    10. try:
    11. # 锁住当前查询到的符合数据,锁住记录后其他的事务无法操作,等当前事务执行完,才允许别的事务进行操作
    12. instance = models.Text_one.objects.select_for_update().filter(id=1)
    13. print(instance)
    14. if instance.count() >= 100 or instance.count() < 150:
    15. models.Text_one.objects.filter(name='小宝').update(count=F('count') + 1)
    16. except Exception:
    17. print('ss')
    18. transaction.savepoint_rollback(sid)
    19. return HttpResponse('ok2')

    bulk_create

    介绍

    1. 批量创建

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

    示例

    1. from rest_framework.views import APIView
    2. from rest_framework.response import Response
    3. from . import models
    4. # models
    5. class UserInfo(models.Model):
    6. username = models.CharField(max_length=66)
    7. # url
    8. path('t3/', views.T3.as_view()),
    9. # view
    10. class T3(APIView):
    11. authentication_classes = []
    12. def get(self, request):
    13. userinfo_data = []
    14. for i in range(10):
    15. # 先生成对象
    16. user = models.UserInfo(username=i)
    17. print("user", user) # user UserInfo object
    18. userinfo_data.append(user)
    19. # 群增,分两次创建
    20. models.UserInfo.objects.bulk_create(userinfo_data,batch_size=2)
    21. return Response('ok')

    bulk_update

    介绍

    1. 群修改

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

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

    示例

    1. from . import models
    2. def t1(request):
    3. instance = models.Text_one.objects.all()
    4. for article in instance:
    5. article.name = "name_updated"
    6. article.title = "title_updated"
    7. models.Text_one.objects.bulk_update(instance, fields=['name'], batch_size=2)
    8. return HttpResponse('ok1')

    其他

    源码

    1. # 源码
    2. def select_for_update(self, nowait=False, skip_locked=False):
    3. """
    4. Returns a new QuerySet instance that will select objects with a
    5. FOR UPDATE lock.
    6. """
    7. if nowait and skip_locked:
    8. raise ValueError('The nowait option cannot be used with skip_locked.')
    9. obj = self._clone()
    10. obj._for_write = True
    11. obj.query.select_for_update = True
    12. obj.query.select_for_update_nowait = nowait
    13. obj.query.select_for_update_skip_locked = skip_locked
    14. 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

  • 相关阅读:
    分布式光伏管理系统具有什么功能?有推荐吗?
    ModelBox开发体验:使用YOLOv3做口罩检测
    python多线程示例
    计算机组成原理---第六章总线---总线概述---选择题
    JavaScript 进阶03
    四、JAVA语言基础
    flink udtaf 常年不能用
    爽爆了!字节架构师纯手打Java技术小册(故事版)开源分享
    二级建造师【管理】第一章:施工方的项目管理
    leetCode 1143.最长公共子序列 动态规划
  • 原文地址:https://blog.csdn.net/qq_52385631/article/details/126893275
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号