购物车cart.html页面加form表单提交
<form method="post" action="{% url 'order:place' %}"> {# 提交到/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.unite }}</em></li> <li class="col04">{{ sku.unite }}</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>
视图函数views.py添加orderplace功能
from django.shortcuts import render, redirect from django.core.urlresolvers import reverse from django.http import JsonResponse from django.views.generic import View from user.models import Address from goods.models import GoodsSKU from orders.models import OrderInfo, OrderGoods from django_redis import get_redis_connection # 连接redis from utils.mixin import LoginRequiredMinxin # 登录验证 from datetime import datetime # Create your views here. # /order/place class OrderPlaceView(LoginRequiredMinxin, View): '''提交订单页面显示''' def post(self, request): '''提交订单页面显示''' # 获取登录的用户 user = request.user # 获取参数sku_ids sku_ids = request.POST.getlist('sku_ids') # [1,26] # 校验参数 if not sku_ids: # 跳转到购物车页面 return redirect(reverse('cart:show')) conn = get_redis_connection('default') cart_key = 'cart_%d'%user.id skus = [] # 保存商品的总件数和总价格 total_count = 0 total_price = 0 # 遍历sku_ids获取用户要购买的商品的信息 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增加属性count,保存购买商品的数量 sku.count = count # 动态给sku增加属性amount,保存购买商品的小计 sku.amount = amount # 追加 skus.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) # [1,25]->1,25 把列表拼接成字符串形式传参 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.html
{% extends 'layout/base_no_cart.html' %} {% load staticfiles %} {% block title %}天天生鲜-提交订单{% endblock title %} {% block page_title %}提交订单{% endblock page_title %} {% block body %} <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, 支付方式, 要购买的商品id字符串 addr_id = $('input[name="addr_id"]:checked').val() // 获取地址 pay_method = $('input[name="pay_style"]:checked').val() // 获取支付方式 sku_ids = $(this).attr('sku_ids') // 获取商品id拼接的字符串 csrf = $('input[name="csrfmiddlewaretoken"]').val() // alert(addr_id+":"+pay_method+':'+sku_ids) // 组织参数 params = {'addr_id':addr_id, 'pay_method':pay_method, 'sku_ids':sku_ids, 'csrfmiddlewaretoken':csrf} // 发起ajax post请求,访问/order/commit, 传递的参数: addr_id pay_method, sku_ids $.post('/order/commit', params, function (data) { if (data.res == 5){ // 创建成功 alert('创建成功') } else{ alert(data.errmsg) } }) {# localStorage.setItem('order_finish',2);#} {##} {# $('.popup_con').fadeIn('fast', function() {#} {##} {# setTimeout(function(){#} {# $('.popup_con').fadeOut('fast',function(){#} {# window.location.href = 'index.html';#} {# }); #} {# },3000)#} {# #} {# });#} }); </script> {% endblock bottomfiles %}
后台views.py处理订单功能orderCommit
# 前端传递的参数:地址id(addr_id) 支付方式(pay_method) 用户要购买的商品id字符串(sku_ids) # mysql事务: 一组sql操作,要么都成功,要么都失败 # 高并发:秒杀 # 支付宝支付 class OrderCommitView(View): '''订单创建''' def post(self, request): '''订单创建''' # 判断用户是否登录 user = request.user if 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') # 1,3 # 校验参数 if not all([addr_id, pay_method, sku_ids]): return JsonResponse({'res':1, 'errmsg':'参数不完整'}) # 校验支付方式 if pay_method not in OrderInfo.PAY_METHODS.keys(): # 需要在orders/model.py中添加PAY_METHODS字典 return JsonResponse({'res':2, 'errmsg':'非法的支付方式'}) # 校验地址 try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: # 地址不存在 return JsonResponse({'res':3, 'errmsg':'地址非法'}) # todo: 创建订单核心业务 # 组织参数 # 订单id: 20171122181630+用户id order_id = datetime.now().strftime('%Y%m%d%H%M%S')+str(user.id) # 运费 transit_price = 10 # 总数目和总金额 total_count = 0 total_price = 0 # todo: 向df_order_info表中添加一条记录 order = OrderInfo.objects.create(order_id=order_id, user=user, addr=addr, pay_method=pay_method, total_count=total_count, total_price=total_price, transit_price=transit_price) # todo: 用户的订单中有几个商品,需要向df_order_goods表中加入几条记录 conn = get_redis_connection('default') cart_key = 'cart_%d'%user.id sku_ids = sku_ids.split(',') for sku_id in sku_ids: # 获取商品的信息 try: sku = GoodsSKU.objects.get(id=sku_id) except: # 商品不存在 return JsonResponse({'res':4, 'errmsg':'商品不存在'}) # 从redis中获取用户所要购买的商品的数量 count = conn.hget(cart_key, sku_id) # todo: 向df_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_count order.total_price = total_price order.save() # todo: 清除用户购物车中对应的记录 conn.hdel(cart_key, *sku_ids) # 返回应答 return JsonResponse({'res':5, 'message':'创建成功'})
此时需要在orders/models.py中OrderInfo方法中添加字典
class OrderInfo(BaseModel): '''订单模型类''' PAY_METHODS = { '1': "货到付款", '2': "微信支付", '3': "支付宝", '4': '银联支付' } PAY_METHODS_ENUM = { "CASH": 1, "ALIPAY": 2 } ORDER_STATUS_ENUM = { "UNPAID": 1, "UNSEND": 2, "UNRECEIVED": 3, "UNCOMMENT": 4, "FINISHED": 5 }