Python Django,事务,transaction.atomic,事务保存点
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import View
from django.db import transaction # 导入事务
# 类视图 (事务,@transaction.atomic装饰器)
class MyView(View):
@transaction.atomic
# transaction.atomic装饰器可以保证该函数中所有的数据库操作都在一个事务中。
def post(self, request):
# 数据库操作1。。。
# 数据库操作2。。。
return HttpResponse('ok')
# 类视图 (事务,保存点的使用)
class MyView2(View):
@transaction.atomic
def post(self, request):
# 设置事务保存点
s1 = transaction.savepoint() # 可以设置多个保存点
# 数据库操作。。。
# 事务回滚 (如果发生异常,就回滚事务)
transaction.savepoint_rollback(s1) # 可以回滚到指定的保存点
# 提交事务 (如果没有异常,就提交事务)
transaction.savepoint_commit(s1)
# 返回应答
原文链接:https://blog.csdn.net/houyanhua1/article/details/85246618
本人案例:直接上代码了
from rest_framework import serializers
from apps.goods.models import SKU, SKUSpecification
from django.db import transaction
from celery_tasks.detail.tasks import task_generate # 数据模型类:SKU具体规格-->SKUSpecification中定义了外键关联SKU数据模型类,从而在SKUSpecification表中获得spec_id,option_id两个值
class SkuSpecRelatedSerializer(serializers.Serializer):
spec_id = serializers.IntegerField()
option_id = serializers.IntegerField() class SkuSerializer(serializers.ModelSerializer):
# 标准商品spu在SKU 数据模型类model中作为外键, 下面将标准商品以字符串输出
spu = serializers.StringRelatedField(read_only=True)
# 标准商品作为外键,默认有一个隐藏属性spu_id, 尽管下面fields= "__all__",但是隐藏属性字段不会返回数据,如果想要数据需要明确定义
spu_id = serializers.IntegerField() # 指定三级分类category_id作为外键 输出名称
category = serializers.StringRelatedField(read_only=True)
# 定义隐藏属性
category_id = serializers.IntegerField() # 规格信息调用上面的SkuSpecRelatedSerializer
# specs = SkuSpecRelatedSerializer(read_only=True, many=True)
# 创建Sku时需要规格数据,删除read_only=True参数
specs = SkuSpecRelatedSerializer(many=True) class Meta:
model = SKU
# fields = "__all__"
exclude = ['create_time', 'update_time'] # 重写ModelSerializer —— create方法
def create(self, validated_data):
# SKU对应的表中没有属性specs,所以需要从字典中删除
specs = validated_data.pop('specs')
# 调用父类方法实现SKU对象创建
# instance = super().create(validated_data)
with transaction.atomic(): # 禁止自动提交,保证该函数中的所有数据库操作在同一个事物中,第一个数据库操作1即使成功保存到数据库中,只要第2个数据操作失败,那么所有该段代码所有设计的都会更改回滚到原来
sid = transaction.savepoint() # 开启事务设置事务保存点
try:
# 直接创建SKU对象
instance = SKU.objects.create(**validated_data)
# 遍历,创建SKU规格对象
for item in specs:
spec_id = item.get('spec_id')
option_id = item.get('option_id')
SKUSpecification.objects.create(sku_id=instance.id, spec_id=spec_id, option_id=option_id)
except:
transaction.savepoint_rollback(sid) # 失败回滚事务(如果数据库操作发生异常,回滚到设置的事务保存点)
raise serializers.ValidationError("数据保存失败")
else:
transaction.savepoint_commit(sid) # 如果没有异常,成功提交事物 # 为Sku生成静态文件
task_generate.delay(instance.id)
return instance
案例2:事务--支付:
#coding=utf-8
import sys
import MySQLdb
class TransferMoney(object):
def __init__(self,conn):
self.conn = conn
#检查账户是否合法
def check_acct_avaiable(self,acctid):
cursor = self.conn.cursor()
try:
sql = "select * from account where acctid=%s" % acctid
cursor.execute(sql)
print "check account:" + sql
rs = cursor.fetchall()
if len(rs) != 1:
raise Exception("account %s illega" % acctid)
finally:
cursor.close()
#检查是否有足够的钱
def has_enough_money(self,acctid,money):
cursor = self.conn.cursor()
try:
sql = "select * from account where acctid=%s and money > %s" % (acctid,money)
cursor.execute(sql)
print "has enough money:" + sql
rs = cursor.fetchall()
if len(rs) != 1:
raise Exception("account %s not enough money" % acctid)
finally:
cursor.close()
#账户减钱
def reduce_money(self,acctid,money):
cursor = self.conn.cursor()
try:
sql = "update account set money = money-%s where acctid = %s" % (money,acctid)
cursor.execute(sql)
print "reduce_money:" + sql
if cursor.rowcount != 1:
raise Exception("reduce money fail %s" % acctid)
finally:
cursor.close()
#账户加钱
def add_money(self,acctid,money):
cursor = self.conn.cursor()
try:
sql = "update account set money = money+%s where acctid = %s" % (money,acctid)
cursor.execute(sql)
print "add_money:" + sql
if cursor.rowcount != 1:
raise Exception("add money fail %s" % acctid)
finally:
cursor.close()
#主执行语句
def transfer(self,source_acctid,target_acctid,money):
try:
self.check_acct_avaiable(source_acctid)
self.check_acct_avaiable(target_acctid)
self.has_enough_money(source_acctid,money)
self.reduce_money(source_acctid,money)
self.add_money(target_acctid,money)
self.conn.commit()
except Exception as e:
self.conn.rollback()
raise e
if __name__ == "__main__":
source_acctid = sys.argv[1]
target_acctid = sys.argv[2]
money = sys.argv[3]
conn = MySQLdb.Connect(host = '127.0.0.1',port=3306,user='root',passwd='',db='test',charset='utf8')
tr_money = TransferMoney(conn)
try:
tr_money.transfer(source_acctid,target_acctid,money)
except Exception as e:
print "Happen:" + str(e)
finally:
conn.close()
针对个人代码总结:
导包transaction
设置该函数中的所有数据库操作在同一个事物中,第一个数据库操作1即使成功保存到数据库中,只要第2个数据操作失败,那么所有该段代码所有涉及的数据库操作都会更改回滚到原来。
with transaction.atomic()
设置事务保存点并开启事务
sid = transaction.savepoint() # 开启事务设置事务保存点
数据库读写操作
操作1
操作2
失败回滚事务(条件:任意一个操作失败,数据库操作发生异常,回滚到设置的事务保存点)
transaction.savepoint_rollback(sid)
raise serializers.ValidationError("数据保存失败")成功(条件:操作1和2都成功,提交事务)
transaction.savepoint_commit(sid) # 如果没有异常,成功提交事务
Python Django,事务,transaction.atomic,事务保存点的更多相关文章
- Java进阶知识24 Spring的事务管理(事务回滚)
1.事务控制概述 1.1.编程式事务控制 自己手动控制事务,就叫做编程式事务控制. Jdbc代码: connection.setAutoCommit(false); ...
- Django之ORM中事务和锁
ORM事务: 事务: 数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成. 事务的特点: 并非任意的对数据库的操作序列都是数据库事务.数据库事务拥有以下四 ...
- Django中的原子事务相关注意事项
Django中的原子事务支持(transaction.atomic)方式函数装饰器或者with语句,这种方式特别是前者和spring里面的AOP事务支持方式基本等同,当然其实质方式都是原始的try.. ...
- Django的锁和事务
Django的锁和事务 锁 select_for_update(nowait=False, skip_locked=False) 返回一个锁住行直到事务结束的查询集,如果数据库支持,它将生成一个 SE ...
- redis 在 php 中的应用(事务 [ Transaction ] 篇)
本文为我阅读了 redis参考手册 之后编写,注意 php_redis 和 redis-cli 的区别(主要是返回值类型和参数用法) 目录: Transaction(事务) WATCH UNWATCH ...
- 事务 TRANSACTION
事务是数据库中一个但单独的执行单元(Unit),他通常由高级数据库操作语言(如SQL)或编程语言(如C++.Java)编写的用户程序的执行所引起.当在数据库中更改数据成功时,在事务中更改的数据便会提交 ...
- atitit.spring hibernate的事务机制 spring不能保存对象的解决
atitit.spring hibernate的事务机制 spring不能保存对象的解决 sessionFactory.openSession() 不能..log黑头马sql语言.. sessionF ...
- transaction 数据库事务 roolback 回滚
事务是恢复和并发控制的基本单位 https://baike.baidu.com/item/数据库事务/9744607 事务有三种模型: 1.隐式事务是指每一条数据操作语句都自动地成为一个事务,事务的开 ...
- redis源码分析之事务Transaction(下)
接着上一篇,这篇文章分析一下redis事务操作中multi,exec,discard三个核心命令. 原文地址:http://www.jianshu.com/p/e22615586595 看本篇文章前需 ...
随机推荐
- 一泡尿的时间,快速读懂QUIC协议
1.TCP协议到底怎么了? 现时的互联网应用中,Web平台(准确地说是基于HTTP及其延伸协议的客户端/服务器应用)的数据传输都基于 TCP 协议. 但TCP 协议在创建连接之前需要进行三次握手(如下 ...
- Python中通过csv的writerow输出的内容有多余的空行两种方法
第一种方法 如下生成的csv文件会有多个空行 import csv #python2可以用file替代open with open("test.csv","w" ...
- Flask 教程 第十一章:美化
本文翻译自The Flask Mega-Tutorial Part XI: Facelift 这是Flask Mega-Tutorial系列的第十一部分,我将告诉你如何用基于Bootstrap用户界面 ...
- MySQL数据库:函数的应用
字符串截取 # 从左边开始 第1个字符 left(字段名,1) # 从那里开始,截取几个 substring(字段名,1,1) str函数 # 连接字符串 concat(s1,s2,s3,--,sn) ...
- 关于ssh的几个功能
这个有许多介绍的. 通过ssh可以实现远程shell命令行登录,x window登录,端口转发,scp文件复制,本地与远程命令间的管道连接,sftp文件传输与管理,包括同步,以及rsync文件同步,还 ...
- python连接sqlite3
一.了解sqlite sqlite是一种嵌入式数据库,它的数据库就是一个文件.由于SQLite本身是用C写的,而且体积很小,所以经常被集成到各种应用程序中,甚至在IOS和Android的APP中都可以 ...
- 这可能是最漂亮的Spring事务管理详解
事务概念回顾 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事物的特性(ACID): 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用 ...
- LeetCode 3: 无重复字符的最长子串 Longest Substring Without Repeating Characters
题目: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. Given a string, find the length of the longest substring withou ...
- [IDA] 自动下载符号
当现实无法自动下载符号时,看下面交互窗口,提示安装 VC++ 2008. 安装成功之后就会自动下载符号.
- 什么是BGP协议
Border Gateway Protocol,边界网关协议,简称BGP,主要用于互联网AS(自治系统)之间的互联. Linux内核原生支持的.专门用在大规模数据中心维护不同的"自治系统&q ...