电商项目订单模块以及高并发的处理

当用户点击去结算时,返回订单页面

cart/cart.html

<form method="post" action="{% url 'order:place' %}">{% for sku in skus %}<ul class="cart_list_td clearfix"><li class="col01"><input type="checkbox" name="sku_ids" value="{{ sku.id }}" checked>li><li class="col02"><img src="{{ sku.image.url }}">li><li class="col03">{{ sku.name }}<br><em>{{ sku.price }}元/{{ sku.unit }}em>li><li class="col04">{{ sku.unit }}li><li class="col05">{{ sku.price }}元li><li class="col06"><div class="num_add"><a href="javascript:;" class="add fl">+a><input type="text" sku_id={{ sku.id }} class="num_show fl" value="{{ sku.count }}"><a href="javascript:;" class="minus fl">-a>	div>li><li class="col07">{{ sku.amount }}元li><li class="col08"><a href="javascript:;">删除a>li>ul>{% endfor %}<ul class="settlements">{% csrf_token %}<li class="col01"><input type="checkbox" name="" checked="">li><li class="col02">全选li><li class="col03">合计(不含运费):<span>¥span><em>{{ total_price }}em><br>共计<b>{{ total_count }}b>件商品li><li class="col04"><input type="submit" value="去结算">li>ul>form>

order/urls.py

from django.conf.urls import url
from order.views import OrderPlaceView
urlpatterns = [url(r'^place$', OrderPlaceView.as_view(), name='place'),  # 提交订单
]

order/views.py

from django.shortcuts import render, redirect
from django.views.generic import View
from django.core.urlresolvers import reverse
from django.http import JsonResponsefrom goods.models import GoodsSKU
from user.models import Addressfrom django_redis import get_redis_connection
from utils.mixin import LoginRequiredMixin# /order/palce
class OrderPlaceView(LoginRequiredMixin, View):"""提价订单显示页面"""def post(self, request):# 获取当前用户user = request.user# 获取参数sku_idssku_ids = request.POST.getlist('sku_ids')print(sku_ids)# 校验参数if not sku_ids:# 跳转到购物车页面return redirect(reverse('cart:show'))conn = get_redis_connection('default')cart_key = 'cart_%d' % user.id# 保存用户购买商的所有品信息skus = []# 记录用户购买商品的总件数和总价格total_count = 0total_price = 0# 遍历sku_ids获取用户要购买的商品id信息for sku_id in sku_ids:# 根据商品的id获取商品对象sku = GoodsSKU.objects.get(id=sku_id)# 获取用户要购买的商品的数量count = conn.hget(cart_key, sku_id)# 计算商品小计amount = sku.price*int(count)# 动态给商品对象添加购买数量和小计属性sku.amount = amountsku.count = countskus.append(sku)# 累加计算用户购买商品总件数和总价格total_count += int(count)total_price += amount# 商品运费 实际开发中,运费会新建一个子系统transit_price = 10# 实付款total_pay = total_price + transit_price# 获取用户收件地址addrs = Address.objects.filter(user=user)# 组织上下文sku_ids = ','.join(sku_ids)context = {"skus": skus,"total_count": total_count,"total_price": total_price,"transit_price": transit_price,"total_pay": total_pay,"addrs": addrs,"sku_ids": sku_ids}# 使用模板return render(request, 'place_order.html', context)

当用户点击提交订单时,会创建订单:

order/place_order.html

<h3 class="common_title">确认收货地址h3><div class="common_list_con clearfix"><dl><dt>寄送到:dt>{% for addr in addrs %}<dd><input type="radio" name="addr_id" value="{{ addr.id }}" {% if addr.is_default %}checked{% endif %}>{{ addr.addr }} ({{ addr.receiver }} 收) {{ addr.phone }}dd>{% endfor %}dl><a href="{% url 'user:address' %}" class="edit_site">编辑收货地址a>div><h3 class="common_title">支付方式h3>	<div class="common_list_con clearfix"><div class="pay_style_con clearfix"><input type="radio" name="pay_style" value="1" checked><label class="cash">货到付款label><input type="radio" name="pay_style" value="2"><label class="weixin">微信支付label><input type="radio" name="pay_style" value="3"><label class="zhifubao">label><input type="radio" name="pay_style" value="4"><label class="bank">银行卡支付label>div>div><h3 class="common_title">商品列表h3><div class="common_list_con clearfix"><ul class="goods_list_th clearfix"><li class="col01">商品名称li><li class="col02">商品单位li><li class="col03">商品价格li><li class="col04">数量li><li class="col05">小计li>		ul>{% for sku in skus %}<ul class="goods_list_td clearfix"><li class="col01">{{ forloop.counter }}li><li class="col02"><img src="{{ sku.image.url }}">li><li class="col03">{{ sku.name }}li><li class="col04">{{ sku.unite }}li><li class="col05">{{ sku.price }}元li><li class="col06">{{ sku.count }}li><li class="col07">{{ sku.amount }}元li>ul>{% endfor %}div><h3 class="common_title">总金额结算h3><div class="common_list_con clearfix"><div class="settle_con"><div class="total_goods_count"><em>{{ total_count }}em>件商品,总金额<b>{{ total_price }}元b>div><div class="transit">运费:<b>{{ transit_price }}元b>div><div class="total_pay">实付款:<b>{{ total_pay }}元b>div>div>div><div class="order_submit clearfix">{% csrf_token %}<a href="javascript:;" sku_ids="{{ sku_ids }}" id="order_btn">提交订单a>div>	
{% endblock body %}
{% block bottom %}<div class="popup_con"><div class="popup"><p>订单提交成功!p>div><div class="mask">div>div>
{% endblock bottom %}
{% block bottomfiles %}<script type="text/javascript" src="{% static 'js/jquery-1.12.4.min.js' %}">script><script type="text/javascript">$('#order_btn').click(function() {// 获取用户选择的地址,支付方式,购买商品id字符串addr_id = $('input[name="addr_id"]:checked').val()pay_method = $('input[name="pay_style"]:checked').val()sku_ids = $(this).attr('sku_ids')csrf = $('input[name="csrfmiddlewaretoken"]').val()// 组织参数params = {"addr_id": addr_id, "pay_method": pay_method, "sku_ids": sku_ids, "csrfmiddlewaretoken": csrf}// 发送ajax post请求,访问/order/commit,传递参数:用户地址,支付方式,购买商品id$.post('{% url "order:commit" %}', params, function (data) {if(data.res == 7){// 创建成功localStorage.setItem('order_finish',2);$('.popup_con').fadeIn('fast', function() {setTimeout(function(){$('.popup_con').fadeOut('fast',function(){window.location.href = '{% url 'user:order' %}';});	},3000)                     });}else{// 创建失败,返回错误信息alert(data.errmsg)}})});script>

order/urls.py

from django.conf.urls import url
from order.views import OrderCommitView
urlpatterns = [url(r'^place$', OrderCommitView.as_view(), name='place'),  # 提交订单
]

order/views.py

使用悲观锁处理订单高并发

from django.shortcuts import render, redirect
from django.views.generic import View
from django.core.urlresolvers import reverse
from django.db import transaction
from django.http import JsonResponse
from datetime import datetimefrom goods.models import GoodsSKU
from user.models import Address
from order.models import OrderInfo, OrderGoodsfrom django_redis import get_redis_connection# /order/commit
# 前端传递参数:订单地址(addr_id),支付方式(pay_method),用户购买商品id字符串
# mysql事物,一组sql操作,要么都成功,要么都失败
# 高并发:秒杀
# 支付宝支付
# 悲观锁处理
class OrderCommitView1(View):"""订单创建"""# mysql事物操作装饰器@transaction.atomicdef post(self, request):# 判断用户是否登录user = request.userif not user.is_authenticated():return JsonResponse({"res": 0, "errmsg": "请登录"})# 接收参数addr_id = request.POST.get('addr_id')pay_method = request.POST.get('pay_method')sku_ids = request.POST.get('sku_ids')# 校验参数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": 2, "errmsg": "非法的支付方式"})# 校验地址try:addr = Address.objects.get(id=addr_id)except Address.DoesNotExist:return JsonResponse({"res": 3, "errmsg": "地址不存在"})# todo: 创建订单核心业务# 组织参数# 订单id:20190217203835+用户idorder_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)# 运费transit_price = 10# 商品总数目和总价格total_count = 0total_price = 0# 设置事物保存点save_id = transaction.savepoint()try:# todo: 向订单信息表(df_order_info)中添加一条数据order = OrderInfo.objects.create(order_id=order_id,user=user,addr=addr,pay_method=pay_method,total_price=total_price,total_count=total_count,transit_price=transit_price)# todo:用户订单里面有几个商品用户订单里面有几个商品,就需要向订单商品表(df_order_goods)中添加几条数据conn = get_redis_connection('default')cart_key = "cart_%d" % user.idsku_ids = sku_ids.split(',')for sku_id in sku_ids:# 获取商品信息try:# select * from df_goods_sku where id=sku_id for update;sku = GoodsSKU.objects.select_for_update().get(id=sku_id)except GoodsSKU.DoesNotExist:# 商品不存在,进行回滚到事物点transaction.savepoint_rollback(save_id)return JsonResponse({"res": 4, "errmsg": "商品不存在"})# 从redis中获取用户所要购买的商品的数量count = conn.hget(cart_key, sku_id)# todo: 判断商品库存if int(count) > sku.stock:# 商品库存不足,进行回滚到事物点transaction.savepoint_rollback(save_id)return JsonResponse({"res": 5, "errmsg": "商品库存不足"})# todo: 向订单商品表(order_goods)中添加一条数据OrderGoods.objects.create(order=order,sku=sku,count=count,price=sku.price)# todo: 更新商品的库存和销量sku.stock -= int(count)sku.sales += int(count)sku.save()# todo: 累加计算订单商品的总数目和总价格amount = sku.price * int(count)total_count += int(count)total_price += amount# todo: 更新订单信息表中的商品总数量和总价格order.total_count = total_countorder.total_price = total_priceorder.save()except Exception as e:transaction.savepoint_rollback(save_id)return JsonResponse({"res": 6, "errmsg": "下单失败"})# 提交事物transaction.savepoint_commit(save_id)# todo: 清除用户购物车中对应的记录conn.hdel(cart_key, *sku_ids)# 返回应答return JsonResponse({"res": 7, "errmsg": "创建订单成功"})

使用乐观锁处理订单高并发

from django.shortcuts import render, redirect
from django.views.generic import View
from django.core.urlresolvers import reverse
from django.db import transaction
from django.http import JsonResponse
from datetime import datetimefrom goods.models import GoodsSKU
from user.models import Address
from order.models import OrderInfo, OrderGoodsfrom django_redis import get_redis_connection# 乐观锁处理
class OrderCommitView(View):"""订单创建"""# mysql事物操作装饰器@transaction.atomicdef post(self, request):# 判断用户是否登录user = request.userif not user.is_authenticated():return JsonResponse({"res": 0, "errmsg": "请登录"})# 接收参数addr_id = request.POST.get('addr_id')pay_method = request.POST.get('pay_method')sku_ids = request.POST.get('sku_ids')# 校验参数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": 2, "errmsg": "非法的支付方式"})# 校验地址try:addr = Address.objects.get(id=addr_id)except Address.DoesNotExist:return JsonResponse({"res": 3, "errmsg": "地址不存在"})# todo: 创建订单核心业务# 组织参数# 订单id:20190217203835+用户idorder_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)# 运费transit_price = 10# 商品总数目和总价格total_count = 0total_price = 0# 设置事物保存点save_id = transaction.savepoint()try:# todo: 向订单信息表(df_order_info)中添加一条数据order = OrderInfo.objects.create(order_id=order_id,user=user,addr=addr,pay_method=pay_method,total_price=total_price,total_count=total_count,transit_price=transit_price)# todo:用户订单里面有几个商品用户订单里面有几个商品,就需要向订单商品表(df_order_goods)中添加几条数据conn = get_redis_connection('default')cart_key = "cart_%d" % user.idsku_ids = sku_ids.split(',')for sku_id in sku_ids:for i in range(3):# 获取商品信息try:sku = GoodsSKU.objects.get(id=sku_id)except GoodsSKU.DoesNotExist:# 商品不存在,进行回滚到事物点transaction.savepoint_rollback(save_id)return JsonResponse({"res": 4, "errmsg": "商品不存在"})# 从redis中获取用户所要购买的商品的数量count = conn.hget(cart_key, sku_id)# todo: 判断商品库存if int(count) > sku.stock:# 商品库存不足,进行回滚到事物点transaction.savepoint_rollback(save_id)return JsonResponse({"res": 5, "errmsg": "商品库存不足"})# todo: 更新商品的库存和销量orgin_stock = sku.stocknew_stock = orgin_stock - int(count)new_sales = sku.sales + int(count)# 更新商品库存# update df_goods_sku set stock=new_stock, sales=new_sales where id=sku_id and stock=orgin_stock# 返回受影响的行数res = GoodsSKU.objects.filter(id=sku_id, stock=orgin_stock).update(stock=new_stock, sales=new_sales)if res == 0:# 尝试的第三次if i == 2:transaction.savepoint_rollback(save_id)return JsonResponse({"res": 8, "errmsg": "下单失败"})continue# todo: 向订单商品表(order_goods)中添加一条数据OrderGoods.objects.create(order=order,sku=sku,count=count,price=sku.price)# todo: 累加计算订单商品的总数目和总价格amount = sku.price * int(count)total_count += int(count)total_price += amount# 跳出循环break# todo: 更新订单信息表中的商品总数量和总价格order.total_count = total_countorder.total_price = total_priceorder.save()except Exception as e:transaction.savepoint_rollback(save_id)return JsonResponse({"res": 6, "errmsg": "下单失败"})# 提交事物transaction.savepoint_commit(save_id)# todo: 清除用户购物车中对应的记录conn.hdel(cart_key, *sku_ids)# 返回应答return JsonResponse({"res": 7, "errmsg": "创建订单成功"})


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部