• 61.django事务的简单应用


    1.Django之数据库事务

    # Django默认事务行为
    Django的默认使用自动提交模式。除非事务处于活动状态,否则每个查询都会立即提交到数据库。
    为了确保ORM操作的完整性,Django自动使用事务或者保存点。
    TestCase由于性能原因,Django的类还会在事务中包装每个测试。
    
    # 事务与HTTP请求
    处理方式:将每个HTTP请求包装在事务中。
    工作原理:在调用视图函数之前,Django启动一个事务。如果视图响应正常,Django会提交事务。如果视图产生异常,Django将回滚事务。
    自定义事务:通过atomic()上下文管理器来使用视图代码中的保存点执行子事务。
    结果:在视图结束时,将提交所有更改或不提交任何更改。
    
    

    2.atomic:

    事务控制(atomic)
    atomic(using = None,savepoint = True)
      using:数据库名称的参数。如果未提供此参数,Django将使用该"default" 数据库。
      savepoint :是否创建保存点。
    atomic允许我们创建一个保证数据库原子性的代码块,如果代码块执行正常,则更改将提交到数据库。如果存在异常,则回滚更改。
    atomic可以嵌套。在这种情况下,当内部块成功完成时,如果稍后在外部块中引发异常,则仍可以回滚其效果。
    
    # atomic 使用方式
    1.作为装饰器使用
    方式一:
    @api_view(['POST'])
    @transaction.atomic
    def test(request):
        obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                           threads=123, modplain="size-10k")
        obj.update(threadname="0000000000000")
        obj.xxx  #这里我直接让保存发现我的数据库没有修改
        return JsonResponse('ok', safe=False
    
    方式二:                        
    @api_view(['POST'])
    @transaction.atomic
    def test(request):
            try:
                obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                                   threads=123, modplain="size-10k")
                obj.update(threadname="0000000000000")
                obj.xxx  # 这里我是用异常捕获了,数据库发生了改变,说明默认事务是基于异常和报错的
            except:
                pass
        return JsonResponse('ok', safe=False)
                            
    2.作为上下文管理器使用
    @api_view(['POST'])
    def test(request):
        with transaction.atomic():
            obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                                   threads=123, modplain="size-10k")
            obj.update(threadname="0000000000000")
            obj.xxx   # 这里我直接让保存发现我的数据库没有修改
    
        return JsonResponse('ok', safe=False)
                            
    @api_view(['POST'])
    def test(request):
        with transaction.atomic():
            try:
                obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                                   threads=123, modplain="size-10k")
                obj.update(threadname="0000000000000")
                obj.xxx   # 这里我是用异常捕获了,数据库发生了改变,说明默认事务是基于异常和报错的
            except:
                pass
        return JsonResponse('ok', safe=False)
                            
    总结:通过上面两个我发现加入你在处理的函数使用异常捕获,事务就不能很好的进行
    

    3.上下文管理器嵌套使用

    1.嵌套捕获异常
    @api_view(['POST'])
    def test(request):
        with transaction.atomic():
            with transaction.atomic():
                obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                                   threads=123, modplain="size-10k")
                obj.update(threadname="0000000000000")
                # obj.xxx
            obj.xxx  # 放在这两个地方都一样,数据库都没有发生改变,所以可以知道如果外部发生异常,会将内部事务的操作仪器回退
        return JsonResponse('ok', safe=False)
    2.嵌套捕获异常
    @api_view(['POST'])
    def test(request):
        with transaction.atomic():
    
            with transaction.atomic():
                try:
                    obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                                       threads=123, modplain="size-10k")
                    obj.update(threadname="0000000000000")
                    obj.xxx  # 数据发生了改变
                except:
                    pass
        return JsonResponse('ok', safe=False)
    --------------------------------------------------------------
    @api_view(['POST'])
    def test(request):
        with transaction.atomic():
    
            with transaction.atomic():
                try:
                    obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                                       threads=123, modplain="size-10k")
                    obj.update(threadname="0000000000000")
                except:
                    pass
                obj.xxx # 数据库没有改变,被外部事务回退了
        return JsonResponse('ok', safe=False)
    
    3.异常是很常见的,但是还需回退被异常捕获的事务,手动回退 ******
    @api_view(['POST'])
    def test(request):
        with transaction.atomic():
            sid = transaction.savepoint()
            try:
                obj = Scenthreadapi.objects.filter(planname="test1011", threadname="thread1012",
                                                   threads=123, modplain="size-10k")
                obj.update(threadname="0000000000000")
                obj.xxx
            except:
                transaction.savepoint_rollback(sid) # 既然异常被捕获了,我直接在异常中手动回退
        return JsonResponse('ok', safe=False)
    
    # Django事务管理代码
        1.进入最外面的atomic块时打开一个事务;
        2.进入内部atomic块时创建保存点;
        3.退出内部块时释放或回滚到保存点;
        4.退出最外面的块时提交或回滚事务。
    atomic(using = None,savepoint = True)
    atomic接受一个using应该是数据库名称的参数。如果未提供此参数,Django将使用该"default" 数据库。
    
    通过将savepoint参数设置为False,可以禁用为内部块创建保存点。如果发生异常,Django将在使用保存点退出第一个父块时执行回滚(如果有保存点),否则执行最外层的块。原子性仍然由外部事务保证。只有当保存点的开销显著时,才应该使用此选项。它的缺点是破坏了上面描述的错误处理。(#加入)
    
    当自动提交被关闭时,可以使用atomic。它只会使用保存点,即使对于最外层的块也是如此。
    
    
  • 相关阅读:
    Dockerfile命令详解
    LXC与Docker Containers的区别
    CSP-S2019游记
    T3
    %%%%%%%%%%%%%%%%
    神炎皇 数学
    2019.9.27
    征途堆积出友情的永恒「堆优化dp」
    星空[好题][题意转化]
    分组[测试点分支+二分图判定]
  • 原文地址:https://www.cnblogs.com/liuzhanghao/p/13185852.html
Copyright © 2020-2023  润新知