django drf 中关于事务的使用

事务处理(transaction)对于Web应用开发至关重要, 它可以维护数据库的完整性, 使整个系统更加安全。比如用户A通过网络转账给用户B,数据库里A账户中的钱已经扣掉,而B账户在接收过程中服务器突然发生了宕机,这时数据库里的数据就不完整了。加入事务处理机制后,如果在一连续交易过程中发生任何意外, 程序将回滚,从而保证数据的完整性。本文将总结事务的四大特性以及Django项目开发中如何操作事务。

事务的四大特性(ACID)
如果想要说明一个数据库或者一个框架支持事务性操作,则必须要满足下面的四大特性:

原子性(Atomicity):整个事务中的所有操作,要么全部完成,要么全部不完成。事务在执行过程中发生错误,会被回滚到事务开始前的状态。

一致性 (Consistency):事务开始之前和事务结束后,数据库的完整性约束没有被破坏。

隔离性(Isolation):隔离性是指当多个用户并发访问数据库时,比如同时访问一张表,数据库每一个用户开启的事务,不能被其他事务所做的操作干扰,多个并发事务之间,应当相互隔离。

持久性(Durability):事务执行成功后,该事务对数据库的更改是持久保存在数据库中的,不会被回滚。

局部开启事务
Django项目中局部开启事务,可以借助于transaction.atomic方法。使用它我们就可以创建一个具备原子性的代码块,一旦代码块正常运行完毕,所有的修改会被提交到数据库。反之,如果有异常,更改会被回滚。

# 案例一:函数视图
 from django.db import transaction

 @transaction.atomic
 def viewfunc(request):
     # This code executes inside a transaction.
     do_stuff()

 # 案例二:基于类的视图
 from django.db import transaction
 from rest_framework.views import APIView

 class OrderAPIView(APIView):
       # 开启事务,当方法执行完以后,自动提交事务
       @transaction.atomic  
       def post(self, request):
           pass 

使用了atomic装饰器,整个视图方法里的代码块都会包裹着一个事务中运行。有时我们希望只对视图方法里一小段代码使用事务,这时可以使用transaction.atomic()显式地开启事务,如下所示:

 from django.db import transaction

 def viewfunc(request):
     # 默认自动提交
     do_stuff()
       
     # 显式地开启事务
     with transaction.atomic():
         # 下面这段代码在事务中执行
         do_more_stuff()

Savepoint回滚
在事务操作中,我们还会经常显式地设置保存点(savepoint)。一旦发生异常或错误,我们使用savepoint_rollback方法让程序回滚到指定的保存点。如果没有问题,就使用savepoint_commit方法提交事务。示例代码如下:

from django.db import transaction

 def viewfunc(request):
     # 默认自动提交
     do_stuff()

     # 显式地开启事务
     with transaction.atomic():
         # 创建事务保存点
         sid = transaction.savepoint()

         try:
             do_more_stuff()
         except Exception as e:
             # 如发生异常,回滚到指定地方。
             transaction.savepoint_rollback(sid)          
         # 如果没有异常,显式地提交一次事务
         transaction.savepoint_commit(sid)

     return HttpResponse("Success")

示例代码

下面的是view试图


from rest_framework.response import Response

from testtranc.models import TestTranc as trancModel

from rest_framework.viewsets import GenericViewSet

from rest_framework.decorators import action

from testtranc.Serializers.trancSerializer import TestTrancSerialize

from django.db import transaction

from django.db import connections


from rest_framework import status

class TestTrancView(GenericViewSet):
    queryset = trancModel.objects.all()
    serializer_class = TestTrancSerialize

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    def create(self, request, *args, **kwargs):
        try:
            with transaction.atomic():
                serializer = self.get_serializer(data=request.data)
                serializer.is_valid(raise_exception=True)
                serializer.save()
                self.runsql()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
        except:
            return Response("失败", status=status.HTTP_404_NOT_FOUND)

    def runsql(self):
        with connections['default'].cursor() as cursor:
            cursor.execute("insert into testtran (name,age) values('eee',100)")


model

from django.db import models


class TestTranc(models.Model):
    id = models.BigAutoField(primary_key=True,verbose_name='主键')
    name = models.CharField(max_length=100,blank=False,null=False,unique=True,verbose_name="姓名")
    age = models.IntegerField(blank=False,null=False)

    class Meta:
        db_table = 'testtran'
# Create your models here.

serialize

from rest_framework.serializers import ModelSerializer
from testtranc.models import TestTranc

class TestTrancSerialize(ModelSerializer):
    class Meta:
        model = TestTranc
        fields = '__all__'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值