• Django中的事务操作


    Django中的事务操作


    事务干货:https://zhuanlan.zhihu.com/p/93067082

    事务使用:https://www.cnblogs.com/oklizz/p/11240212.html

    (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)

    在写项目时,特别是view中,我们可能需要进行多个业务操作(不仅仅是操作sql)。比如说:在编辑case的接口,我需要对case对应的interface进行新增/修改/删除操作,以及对case进行更新操作;我需要这样实现:把这四个步骤当成个事务,当其中有一个步骤失败,则回滚不执行;只有都成功时,才执行这四个步骤。

    (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)

    atomic提供两种方案实现事务

    1、with 语句用法:

    with 语句用法:可以灵活的有选择性的把某些 MySQL 数据库的操作看做一个事务。而且不用关心视图的类型。

    from django.db import transaction
    
    def viewfunc(request):
      # 这部分代码不在事务中,会被 Django 自动提交
      ......
    
      with transaction.atomic():
          # 这部分代码会在事务中执行
          ......
    

    (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)

    from django.db import transaction
    
    # 创建保存点
    save_id = transaction.savepoint()
    
    # 回滚到保存点
    transaction.savepoint_rollback(save_id)
    
    # 提交从保存点到当前状态的所有数据库事务操作
    transaction.savepoint_commit(save_id)
    

    (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)

    举个栗子

    1.创建一个项目,新建一个APP

    2.通过ORM创建生成表

    from django.db import models
    
    
    class Goods(models.Model):
        title = models.CharField(max_length=50, verbose_name='标题')
        price = models.IntegerField(verbose_name='价格')
        date = models.CharField(max_length=50, null=True, verbose_name='出发日期')
        satisfaction = models.CharField(verbose_name='满意度', max_length=20)
        img = models.ImageField(upload_to='static/img', null=True, blank=True)
        sum_evaluate = models.IntegerField(verbose_name='总评价人数')
        sum_number = models.IntegerField(verbose_name='总出游人数')
    
    class Comment(models.Model):
        comment = models.CharField(max_length=250, verbose_name='评论')
        goods = models.ForeignKey(Goods, on_delete=models.CASCADE, null=True)
    
    

    随便建2张表模拟一下·····

    3.我们给数据库加两条数据,用来两个用户之间的数据添加

    4.配置URL

    5.创建对应的视图函数

    class CommentView(APIView):
        def post(self, request):
            goods_id = request.data.get('goods_id')
            comment = request.data.get('comment')
            if not all([goods_id, comment]):
                return Response({'code': 400, 'msg': '参数不全'})
    
            else:
                # 创建保存点
                save_id = transaction.savepoint()
                # 这部分代码不在事务中,会被 Django 自动提交
                with transaction.atomic():
                # 这部分代码会在事务中执行
                    try:
                        Comment.objects.create(goods_id=goods_id, comment=comment)
                        # Goods object (1)
                        # good_obj = Goods.objects.get(id=goods_id)
                        good_obj = Goods.objects.get(name=goods_id)
                        good_obj.sum_evaluate += 1
                        good_obj.save()
    
                        # 提交从保存点到当前状态的所有数据库事务操作
                        # transaction.savepoint_commit(save_id)
                        return Response({'code': 200, 'msg': '添加成功'})
                    except Exception as e:
                        #捕获异常回滚
                        transaction.savepoint_rollback(save_id)
                        return Response({'code': 400, 'msg': '添加失败', 'errors': e})
    
    

    然后我们请求会进行一些数据添加

    6.这样是没有办法体现出我们事务的原子性的 现在我们让他报错

    # good_obj = Goods.objects.get(name=goods_id)
    

    2、装饰器用法:

    装饰器用法:整个视图中所有 MySQL 数据库的操作都看做一个事务,范围太大,不够灵活。而且无法直接作用于类视图

    from django.db import transaction
    
    @transaction.atomic
    def index(request):
        // ORM操作
        return ....
      # 这些代码会在一个事务中执行	
    

    (~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)

    from django.db import transaction
    
    class CommentView(APIView):
        @transaction.atomic
        def post(self, request):
            goods_id = request.data.get('goods_id')
            comment = request.data.get('comment')
            if not all([goods_id, comment]):
                return Response({'code': 400, 'msg': '参数不全'})
    
            else:
                Comment.objects.create(goods_id=goods_id, comment=comment)
                # Goods object (1)
                # good_obj = Goods.objects.get(id=goods_id)
                good_obj = Goods.objects.get(name=goods_id)
                good_obj.sum_evaluate += 1
                good_obj.save()
    
                return Response({'code': 200, 'msg': '添加成功'})
         
    

    注意

    在原子块中不要进行错误捕获

    当退出原子块的时候,Django会去查看它是否正常退出或者是否有异常来确定是否提交或者回滚

    如果你捕获并处理了原子块中的异常,可能会隐藏Django中发生问题的事实。这样可能会造成非预期的行为。

    从小白到大神的蜕变~~
  • 相关阅读:
    4.方向-世界坐标系
    3.Unity3d物体操作常用按键
    2.Unity3d常用按键
    1.Unity3d的新建场景和保存场景
    MySQL CodeFirst的配置与注意事项
    HNU暑假训练第一场C.Ninja Map
    牛客暑假多校第二场J-farm
    牛客暑假多校第一场J-Different Integers
    主席树设计与实现
    博弈论的一些理解
  • 原文地址:https://www.cnblogs.com/tjw-bk/p/13975220.html
Copyright © 2020-2023  润新知