django项目学习八

订单模块

事务

Django 默认的事务行为
Django 默认的事务行为是自动提交。除非事务正在执行,每个查询将会马上自动提交>到数据库。
Django 自动使用事务或还原点,以确保需多次查询的 ORM 操作的一致性,特别是 >delete() 和 update() 操作。

为什么需要事务?
解释详情请见链接:https://blog.csdn.net/qq_24997655/article/details/78757347

这个项目中,订单生产需要 创建 添加OrderInfo订单数据,添加OrderGoods订单商品数据,修改GoodsSku商品的库存和销量,还需要修改购物车,需要修改三张表,和redis数据库数据。为了保证这些流程的一致性,就需要开启事务。
django的事务api,详见:https://docs.djangoproject.com/zh-hans/2.2/topics/db/transactions/

使用的代码如下:

from django.db import transaction # 事务管理类
from datetime import datetime
from django_redis import get_redis_connection

class OrderSaveView(View):
    '''提交订单类'''
    @transaction.atomic
    def post(self, request):
        addr_id = request.POST.get("addr_id")
        pay_method = request.POST.get('pay_method')
        sku_ids = request.POST.get('sku_ids')

        user =request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '未登录'})

        if not all([addr_id, pay_method, sku_ids]):
            return JsonResponse({'res': -1, 'errmsg': '数据不完整'})

        if pay_method not in OrderInfo.PAY_METHODS.keys():
            return JsonResponse({'res': -1, 'errmsg': '支付方式非法'})
        try:
            address = Address.objects.get(id=addr_id)
        except Address.DoesNotExist:
            return JsonResponse({'res': -1, 'errmsg': '地址非法'})
		# 设置保存点
        sid = transaction.savepoint()

        try:
            order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)
            print("order_id:", order_id)
            total_count = 0
            total_price = 0
            transit_price = 10

            orderInfo = OrderInfo.objects.create(order_id=order_id, user=user,
                                     addr=address, total_count=total_count,
                                     total_price=total_price, transit_price=transit_price,
                                     pay_method=pay_method)


            conn = get_redis_connection('default')
            cart_key = 'cart_%d' % user.id
            skus_ids = sku_ids.split(",")
            for sku_id in skus_ids:
                try:
                    # 悲观锁
                   sku = GoodsSKU.objects.select_for_update().get(id=sku_id)
                except GoodsSKU.DoesNotExist:
                    return JsonResponse({'res': -1, 'errmsg': '找不到这件商品'})

                # 获取购物车商品数量
                count = conn.hget(cart_key, sku.id)
                amount = int(count)*sku.price

                if int(count) > sku.stock:
                    return JsonResponse({'res': -1, 'errmsg': "%s没有库存" % sku.name})

                # 更新库存和销量
                sku.stock -= int(count)
                sku.sales += int(count)
                sku.save()

                # 创建订单商品详情
                OrderGoods.objects.create(order=orderInfo, sku=sku, count=count, price=sku.price)

                # 计算总商品件数和总金额
                total_count += int(count)
                total_price += amount
            # 更新订单商品总数和商品总金额
            orderInfo.total_count = total_count
            orderInfo.total_price = total_price
            orderInfo.save()

            # 清空购物车
            conn.hdel(cart_key, *skus_ids)
            # 保存点提交事务
            transaction.savepoint_commit(sid)

            return JsonResponse({'res': 1, 'msg': "订单提交成功"})

        except Exception as e:
        	# 回滚到指定保存点
            transaction.savepoint_rollback(sid)
            return JsonResponse({'res': -1, 'errmsg': "订单提交失败"})

订单并发处理

django项目学习八_第1张图片

(1) 悲观锁

select * from df_goods_sku where id=17 for update;
django项目学习八_第2张图片
悲观锁获取数据时对数据行了锁定,其他事务要想获取锁,必须等原事务结束。

(2) 乐观锁

查询时不锁数据,提交更改时进行判断.
update df_goods_sku set stock=0, sales=1 where id=17 and stock=1;

冲突比较少的时候,使用乐观锁。
冲突比较多的时候,使用悲观锁。

你可能感兴趣的:(python,mysql,django,python,orm)