天天生鲜Django项目③

13-订单生成

03_提交订单页面显示

class OrderPlaceView(LoginRequiredMixin, View):
    """订单提交页面"""

    def post(self, request):

        user = request.user

        # 获取提交的商品ids
        sku_ids = request.POST.getList('sku_ids')

        # 验证sku_ids
        if not sku_ids:
            return redirect(reverse('cart:show'))

        conn = get_redis_connection('default')
        cart_key = 'cart_%s' % user.id
        skus = []
        total_count = 0
        total_price = 0
        for sku_id in sku_ids:
            # 获取商品的信息和数量
            sku = GoodsSKU.objects.get(id=sku_id)
            count = conn.hget(cart_key, sku_id)
            amount = sku.price * int(count)

            # 动态添加数量和小计
            sku.count = count
            sku.amount = amount
            skus.append(sku)

            total_price += amount
            total_count += int(count)

        # 写死运费
        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)

04_创建订单前端js

{% 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')
            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){
                    // 创建成功
                    localStorage.setItem('order_finish',2);
                    $('.popup_con').fadeIn('fast', function() {

                        setTimeout(function(){
                            $('.popup_con').fadeOut('fast',function(){
                                window.location.href = '/user/order/1';
                            });
                        },3000)

                    });
                }
                else{
                    alert(data.errmsg)
                }
            })



		});
	</script>
{% endblock bottomfiles %}

01_订单生成_mysql事务概念

在这里插入图片描述
在这里插入图片描述

02_订单生成_django中使用事务

from django.db import transaction

 # 设置事务保存点
save_id = transaction.savepoint()
try:
    # 向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)

    # 用户的订单中有几个商品,需要向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:
            # select * from df_goods_sku where id=sku_id for update;
            # 在查询的时候就进行加锁,其他进程需要等待该进行commit或者rollback之后才释放锁

            """
                悲观锁就是在查询的时候就进行枷锁
                乐观锁不在查询的时候加锁,而是在判断更新库存的时候和之前查到的库存是不是相等
                不相等的话说明其间别人把库存进行了修改
            """
            print(sku_id)
            sku = GoodsSKU.objects.get(id=sku_id) # .select_for_update()
        except:
            # 商品不存在
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 4, 'errmsg': '商品不存在'})

        # 从redis中获取用户所要购买的商品的数量
        count = conn.hget(cart_key, sku_id)

        # 判断商品的库存
        if int(count) > sku.stock:
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 6, 'errmsg': '商品库存不足'})

        # 向df_order_goods表中添加一条记录
        OrderGoods.objects.create(order=order,
                                  sku=sku,
                                  count=count,
                                  price=sku.price)

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

        # 累加计算订单商品的总数量和总价格
        amount = sku.price * int(count)
        total_count += int(count)
        total_price += amount

    # 更新订单信息表中的商品的总数量和总价格
    order.total_count = total_count
    order.total_price = total_price
    order.save()
except Exception as e:
    transaction.savepoint_rollback(save_id)
    return JsonResponse({'res': 7, 'errmsg': '下单失败'})

# 提交事务,否则不会提交
transaction.savepoint_commit(save_id)

14-订单并发处理

02_订单并发_悲观锁

当我们要对一个数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制

但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会。另外还会降低并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数据。

class OrderCommitView(View):
    """订单提交:悲观锁"""

    @transaction.atomic
    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')

        # 验证参数
        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 as e:
            return JsonResponse({'res': 3, 'errmsg': '地址不存在'})

        # 创建订单核心业务
        # 创建订单核心业务

        # 组织参数
        # 订单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

        # 设置事务保存点
        save_id = transaction.savepoint()
        try:
            # 向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)

            # 用户的订单中有几个商品,需要向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:
                    # select * from df_goods_sku where id=sku_id for update;
                    # 在查询的时候就进行加锁,其他进程需要等待该进行commit或者rollback之后才释放锁

                    """
                        悲观锁就是在查询的时候就进行枷锁
                        乐观锁不在查询的时候加锁,而是在判断更新库存的时候和之前查到的库存是不是相等
                        不相等的话说明其间别人把库存进行了修改
                    """
                    sku = GoodsSKU.objects.select_for_update().get(id=sku_id) # .select_for_update()
                except:
                    # 商品不存在
                    transaction.savepoint_rollback(save_id)
                    return JsonResponse({'res': 4, 'errmsg': '商品不存在'})
                # print(user.id ,sku.stock)
                # 从redis中获取用户所要购买的商品的数量
                count = conn.hget(cart_key, sku_id)

                # 判断商品的库存
                if int(count) > sku.stock:
                    transaction.savepoint_rollback(save_id)
                    return JsonResponse({'res': 6, 'errmsg': '商品库存不足'})

                # 向df_order_goods表中添加一条记录
                OrderGoods.objects.create(order=order,
                                          sku=sku,
                                          count=count,
                                          price=sku.price)

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

                # 累加计算订单商品的总数量和总价格
                amount = sku.price * int(count)
                total_count += int(count)
                total_price += amount

            # 更新订单信息表中的商品的总数量和总价格
            order.total_count = total_count
            order.total_price = total_price
            order.save()
        except Exception as e:
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 7, 'errmsg': '下单失败'})

        # 提交事务,否则不会提交
        transaction.savepoint_commit(save_id)

        # 清除用户购物车中对应的记录
        conn.hdel(cart_key, *sku_ids)

        # 返回应答
        return JsonResponse({'res': 5, 'message': '创建成功'})

03_订单并发_乐观锁

乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做

乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。

尝试三次判断,查看更新后数据是否保持一致

class OrderCommitView1(View):
    """
    订单提交:乐观锁
    需要在mysql的配置文件中添加mysql的事务隔离级别为read-commited只读提交的内容
    防止读取不到另一个事务提交后的更新数据
    """

    @transaction.atomic
    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')

        # 验证参数
        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 as e:
            return JsonResponse({'res': 3, 'errmsg': '地址不存在'})

        # 创建订单核心业务
        # 创建订单核心业务

        # 组织参数
        # 订单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

        # 设置事务保存点
        save_id = transaction.savepoint()
        try:
            # 向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)

            # 用户的订单中有几个商品,需要向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:
                # 获取商品的信息
                for i in range(3):

                    try:
                        # select * from df_goods_sku where id=sku_id for update;
                        # 在查询的时候就进行加锁,其他进程需要等待该进行commit或者rollback之后才释放锁

                        """
                            悲观锁就是在查询的时候就进行枷锁
                            乐观锁不在查询的时候加锁,而是在判断更新库存的时候和之前查到的库存是不是相等
                            不相等的话说明其间别人把库存进行了修改
                        """
                        sku = GoodsSKU.objects.get(id=sku_id)
                    except:
                        # 商品不存在
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'res': 4, 'errmsg': '商品不存在'})

                    print('user:%d stock:%d' % (user.id, sku.stock))
                    # 从redis中获取用户所要购买的商品的数量
                    count = conn.hget(cart_key, sku_id)

                    # 判断商品的库存
                    if int(count) > sku.stock:
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'res': 6, 'errmsg': '商品库存不足'})

                    # 更新商品的库存和销量
                    orgin_stock = sku.stock
                    new_stock = orgin_stock - int(count)
                    new_sales = sku.sales + int(count)

                    # 返回受影响的行数,表示1更新成功,返回0表示更新失败
                    res = GoodsSKU.objects.filter(id=sku_id, stock=orgin_stock) \
                        .update(stock=new_stock, sales=new_sales)

                    if res == 0:
                        if i == 2:
                            # 尝试到第3次
                            transaction.savepoint_rollback(save_id)
                            return JsonResponse({'res': 7, 'errmsg': '下单失败'})
                        else:
                            continue

                    # 向df_order_goods表中添加一条记录
                    OrderGoods.objects.create(order=order,
                                              sku=sku,
                                              count=count,
                                              price=sku.price)

                    # 累加计算订单商品的总数量和总价格
                    amount = sku.price * int(count)
                    total_count += int(count)
                    total_price += amount

                    # 若用户不到3此酒秒杀成功直接跳出循环
                    break

            # 更新订单信息表中的商品的总数量和总价格
            order.total_count = total_count
            order.total_price = total_price
            order.save()
        except Exception as e:
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 7, 'errmsg': '下单失败'})

        # 提交事务,否则不会提交
        transaction.savepoint_commit(save_id)

        # 清除用户购物车中对应的记录
        conn.hdel(cart_key, *sku_ids)

        # 返回应答
        return JsonResponse({'res': 5, 'message': '创建成功'})

并发处理总结

在这里插入图片描述

区别

悲观锁就是在查询的时候就进行枷锁
乐观锁不在查询的时候加锁,而是在判断更新库存的时候和之前查到的库存是不是相等,不相等的话说明其间别人把库存进行了修改

应用场景

在乐观锁与悲观锁的选择上面,主要看下两者的区别以及适用场景就可以了。

乐观锁并未真正加锁,效率高。一旦锁的粒度掌握不好,更新失败的概率就会比较高,容易发生业务失败。

悲观锁依赖数据库锁,效率低。更新失败的概率比较低。

随着互联网三高架构(高并发、高性能、高可用)的提出,悲观锁已经越来越少的被使用到生产环境中了,尤其是并发量比较大的业务场景。

事务的隔离性

在这里插入图片描述
在这里插入图片描述

修改隔离性

需要在mysql的配置文件中添加mysql的事务隔离级别为read-commited只读提交的内容
防止读取不到另一个事务提交后的更新数据
在这里插入图片描述
在这里插入图片描述

15-订单支付、评论

用户中心-订单页面

class UserOrderView(LoginRequiredMixin, View):
    """用户中心-订单页面"""

    def get(self, request, page):

        user = request.user

        # 数据库获取用户的订单信息
        orders = OrderInfo.objects.filter(user=user).order_by('-create_time')

        for order in orders:
            order_skus = OrderGoods.objects.filter(order_id=order.order_id)

            for order_sku in order_skus:
                # 计算小计
                amount = order_sku.count * order_sku.price
                order_sku.amount = amount

            # 保存单个订单商品的信息
            order.status_name = OrderInfo.ORDER_STATUS[order.order_status]
            order.order_skus = order_skus

        # 进行分页
        paginator = Paginator(orders, 1)

        # 获取第page页的内容
        try:
            page = int(page)
        except Exception as e:
            page = 1

        if page > paginator.num_pages:
            page = 1

        # 获取第page页的page对象,废弃因为会加载所有的页码
        order_page = paginator.page(page)

        # 控制限制的页码,只显示最多5个按钮
        # 如果总页数小于5,显示[1-页码]
        # 如果当前页是前三页,显示[1,2,3,4,5]
        # 如果当前页是后三页,显示[4,5,6,7,8] num_pages-4 到num_oages+1
        # 显示当前页,显示当前页的前两页和后两页 [2,3,4,5,6]

        num_pages = paginator.num_pages
        if num_pages < 5:
            pages = range(1, num_pages + 1)
        elif num_pages <= 3:
            pages = range(1, 6)
        elif num_pages - page <= 2:
            pages = range(num_pages-4, num_pages+1)
        else:
            pages = range(page-2, page+3)

        context = {
            'order_page': order_page,
            'pages': pages,
            'page': 'order',
        }

        return render(request, 'user_center_order.html', context)

订单支付_获取支付结果

支付流程

在这里插入图片描述

配置支付宝支付接口

文档 https://github.com/fzlee/alipay

openssl操作

在这里插入图片描述
在这里插入图片描述

沙箱环境

首先,进入蚂蚁金服开放平台官方主页, 点击文档中心的开发文档,往下翻,找到开发工具-沙箱环境
在这里插入图片描述

  1. 将本地公钥alipay_public_key.pem 内容设置为 查看公钥内容

    -----BEGIN PUBLIC KEY-----
    内容
    -----END PUBLIC KEY-----
    
  2. 将 查看支付宝公钥复制本地 alipay_public_key.pem

  3. 将本地 app_private_key.pem文件复制项目中
    在这里插入图片描述
    遇到的错误:
    RSA key format is not supported

在这里插入图片描述

设置沙箱买家 购买

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

前后台代码逻辑

class OrderPayView(View):
    """订单支付"""
    def post(self, request):
        # 判断用户是否登录
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '用户未登录'})

        # 接受参数
        order_id = request.POST.get('order_id')

        # 判断参数
        if not order_id:
            return JsonResponse({'res': 1, 'errmsg': '无效订单id'})

        try:
            order = OrderInfo.objects.get(
                order_id=order_id,
                user=user,
                pay_method=3,
                order_status=1,
            )
        except OrderInfo.DoesNotExist as e:
            return JsonResponse({'res': 2, 'errmsg': '订单错误,无此订单或需要支付宝付款'})

        # 调用支付宝的支付接口
        alipay = AliPay(
            appid="你的APPID",
            # 默认回调url
            app_notify_url=None,
            app_private_key_path=os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem'),
            # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            alipay_public_key_path=os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem'),
            # RSA 或者 RSA2,官网推荐rsa2
            sign_type="RSA",
            debug=True  # 默认False, true表示访问沙箱的dev接口
        )
        # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
        total_pay = order.total_price + order.transit_price
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,
            total_amount=str(total_pay),
            subject='天天生鲜%s' % order_id,
            return_url=None, # "https://example.com",
            notify_url=None # "https://example.com/notify"  # 可选, 不填则使用默认notify url
        )
        # 返回应答,引导html页面跳转去接受支付的dev界面
        pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
        return JsonResponse({'res': 3, 'pay_url': pay_url})
{% block bottomfiles %}
    <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
    <script>
    $('.oper_btn').each(function () {
        // 获取支付状态
        status = $(this).attr('status');
        if (status == 1){
            $(this).text('去支付')
        }
        else if (status == 4){
            $(this).text('去评价')
        }
        else if (status == 5){
            $(this).text('已完成')
        }
    });

    $('.oper_btn').click(function () {
        // 获取status
        status = $(this).attr('status');
        // 获取订单id
        order_id = $(this).attr('order_id');
        if (status == 1){
            // 进行支付
            csrf = $('input[name="csrfmiddlewaretoken"]').val();
            // 组织参数
            params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf};
            // 发起ajax post请求,访问/order/pay, 传递参数:order_id
            $.post('/order/pay', params, function (data) {
                if (data.res == 3){
                    // 引导用户到支付页面
                    window.open(data.pay_url);
                    // 浏览器访问/order/check, 获取支付交易的结果
                    // ajax post 传递参数:order_id
                    $.post('/order/check', params, function (data){
                        if (data.res == 3){
                            alert('支付成功');
                            // 刷新页面
                            location.reload()
                        }
                        else{
                            alert(data.errmsg)
                        }
                    })
                }
                else{
                    alert(data.errmsg)
                }
            })
        }
        else if (status == 4){
            // 其他情况
            // 跳转到评价页面
            location.href = '/order/comment/'+order_id
        }
    })
    </script>
{% endblock bottomfiles %}

获取支付结果

查看开发者文档

在这里插入图片描述
在这里插入图片描述

# ajax post
# 前端传递参数 order_id
# /order/check
class CheckPayView(View):
    """因为没有公网,所以下订单后手动去访问去query支付结果么人不是根据return_url"""

    def post(self, request):
        # 判断用户是否登录
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '用户未登录'})

        # 接受参数
        order_id = request.POST.get('order_id')

        # 判断参数
        if not order_id:
            return JsonResponse({'res': 1, 'errmsg': '无效订单id'})

        try:
            order = OrderInfo.objects.get(
                order_id=order_id,
                user=user,
                pay_method=3,
                order_status=1,
            )
        except OrderInfo.DoesNotExist as e:
            return JsonResponse({'res': 2, 'errmsg': '订单错误'})

        # 调用支付宝的支付接口
        alipay = AliPay(
            appid="你的APPID",
            # 默认回调url
            app_notify_url=None,
            app_private_key_path=os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem'),
            # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            alipay_public_key_path=os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem'),
            # RSA 或者 RSA2,官网推荐rsa2
            sign_type="RSA",
            debug=True  # 默认False, true表示访问沙箱的dev接口
        )

        # 手动查询结果
        # 调用支付宝的交易查询接口
        while True:
            response = alipay.api_alipay_trade_query(order_id)

            # response = {
            #         "trade_no": "2017032121001004070200176844", # 支付宝交易号
            #         "code": "10000", # 接口调用是否成功
            #         "invoice_amount": "20.00",
            #         "open_id": "20880072506750308812798160715407",
            #         "fund_bill_list": [
            #             {
            #                 "amount": "20.00",
            #                 "fund_channel": "ALIPAYACCOUNT"
            #             }
            #         ],
            #         "buyer_logon_id": "csq***@sandbox.com",
            #         "send_pay_date": "2017-03-21 13:29:17",
            #         "receipt_amount": "20.00",
            #         "out_trade_no": "out_trade_no15",
            #         "buyer_pay_amount": "20.00",
            #         "buyer_user_id": "2088102169481075",
            #         "msg": "Success",
            #         "point_amount": "0.00",
            #         "trade_status": "TRADE_SUCCESS", # 支付结果
            #         "total_amount": "20.00"
            # }

            code = response.get('code')

            if code == '10000' and response.get('trade_status') == 'TRADE_SUCCESS':
                # 支付成功
                # 获取支付宝交易号
                trade_no = response.get('trade_no')
                # 更新订单状态
                order.trade_no = trade_no
                order.order_status = 4  # 待评价
                order.save()
                # 返回结果
                return JsonResponse({'res': 3, 'message': '支付成功'})
            elif code == '40004' or (code == '10000' and response.get('trade_status') == 'WAIT_BUYER_PAY'):
                # 等待买家付款
                # 业务处理失败,可能一会就会成功
                import time
                time.sleep(5)
                continue
            else:
                # 支付出错
                print(code)
                return JsonResponse({'res': 4, 'errmsg': '支付失败'})
{% block bottomfiles %}
    <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
    <script>
    $('.oper_btn').each(function () {
        // 获取支付状态
        status = $(this).attr('status');
        if (status == 1){
            $(this).text('去支付')
        }
        else if (status == 4){
            $(this).text('去评价')
        }
        else if (status == 5){
            $(this).text('已完成')
        }
    });

    $('.oper_btn').click(function () {
        // 获取status
        status = $(this).attr('status');
        // 获取订单id
        order_id = $(this).attr('order_id');
        if (status == 1){
            // 进行支付
            csrf = $('input[name="csrfmiddlewaretoken"]').val();
            // 组织参数
            params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf};
            // 发起ajax post请求,访问/order/pay, 传递参数:order_id
            $.post('/order/pay', params, function (data) {
                if (data.res == 3){
                    // 引导用户到支付页面
                    window.open(data.pay_url);
                    // 浏览器访问/order/check, 获取支付交易的结果
                    // ajax post 传递参数:order_id
                    $.post('/order/check', params, function (data){
                        if (data.res == 3){
                            alert('支付成功');
                            // 刷新页面
                            location.reload()
                        }
                        else{
                            alert(data.errmsg)
                        }
                    })
                }
                else{
                    alert(data.errmsg)
                }
            })
        }
        else if (status == 4){
            // 其他情况
            // 跳转到评价页面
            location.href = '/order/comment/'+order_id
        }
    })
    </script>
{% endblock bottomfiles %}

订单评论

/user/order/1
在这里插入图片描述
支付js文件

{% block bottomfiles %}
    <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
    <script>
    $('.oper_btn').each(function () {
        // 获取支付状态
        status = $(this).attr('status');
        if (status == 1){
            $(this).text('去支付')
        }
        else if (status == 4){
            $(this).text('去评价')
        }
        else if (status == 5){
            $(this).text('已完成')
        }
    });

    $('.oper_btn').click(function () {
        // 获取status
        status = $(this).attr('status');
        // 获取订单id
        order_id = $(this).attr('order_id');
        if (status == 1){
            // 进行支付
            csrf = $('input[name="csrfmiddlewaretoken"]').val();
            // 组织参数
            params = {'order_id':order_id, 'csrfmiddlewaretoken':csrf};
            // 发起ajax post请求,访问/order/pay, 传递参数:order_id
            $.post('/order/pay', params, function (data) {
                if (data.res == 3){
                    // 引导用户到支付页面
                    window.open(data.pay_url);
                    // 浏览器访问/order/check, 获取支付交易的结果
                    // ajax post 传递参数:order_id
                    $.post('/order/check', params, function (data){
                        if (data.res == 3){
                            alert('支付成功');
                            // 刷新页面
                            location.reload()
                        }
                        else{
                            alert(data.errmsg)
                        }
                    })
                }
                else{
                    alert(data.errmsg)
                }
            })
        }
        else if (status == 4){
            // 其他情况
            // 跳转到评价页面
            location.href = '/order/comment/'+order_id
        }
    })
    </script>
{% endblock bottomfiles %}

评论 order_comment.html

{% extends 'base_user_center.html' %}
{% load staticfiles %}
{% block title %}天天生鲜-用户中心{% endblock %}
{% block page_title %}用户中心{% endblock page_title %}
{% block right_content %}
        <div class="right_content clearfix">
            <h3 class="common_title2">订单评价</h3>
                <ul class="order_list_th w978 clearfix">
					<li class="col01">{{order.create_time}}</li>
					<li class="col02">订单号:{{order.order_id}}</li>
					<li class="col02 stress">{{order.status_name}}</li>
				</ul>
            <form method="post">
                {% csrf_token %}
                {# 订单id #}
                <input type="hidden" name="order_id" value="{{order.order_id}}">
                {# 订单中有几个商品 #}
                <input type="hidden" name="total_count" value="{{order.order_skus|length}}">
                {% for order_sku in order.order_skus %}
                <table class="order_list_table w980">
                    <tbody>
                        <tr>
                            <td width="80%">
                                <ul class="order_goods_list clearfix">
                                    <li class="col01"><img src="{{ order_sku.sku.image.url }}"></li>
                                    <li class="col02">{{order_sku.sku.name}}<em>{{order_sku.price}}/{{order_sku.sku.unite}}</em></li>
                                    <li class="col03">{{order_sku.count}}</li>
                                </ul>
                            </td>
                            <td width="20%">{{order_sku.amount}}</td>
                        </tr>
                    </tbody>
                </table>
                <div class="site_con">
                    <input type="hidden" name="sku_{{forloop.counter}}" value="{{order_sku.sku.id}}">
                    <div class="form_group form_group2">
                        <label>评价内容:</label>
                        <textarea class="site_area" name="content_{{forloop.counter}}"></textarea>
                    </div>
                </div>
                {% endfor %}
                <input type="submit" name="" value="提交" class="info_submit">
            </form>
        </div>
{% endblock right_content %}

评论后端逻辑

class CommentView(View):
    """订单评论"""
    def get(self, request, order_id):
        """提供评论页面"""
        user = request.user

        # 校验数据
        if not order_id:
            return redirect(reverse('user:order'))

        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user)
        except OrderInfo.DoesNotExist:
            return redirect(reverse("user:order"))

        # 根据订单的状态获取订单的状态标题
        order.status_name = OrderInfo.ORDER_STATUS[order.order_status]

        # 获取订单商品信息
        order_skus = OrderGoods.objects.filter(order_id=order_id)
        for order_sku in order_skus:
            # 计算商品的小计
            amount = order_sku.count*order_sku.price
            # 动态给order_sku增加属性amount,保存商品小计
            order_sku.amount = amount
        # 动态给order增加属性order_skus, 保存订单商品信息
        order.order_skus = order_skus

        # 使用模板
        return render(request, "order_comment.html", {"order": order})

    def post(self, request, order_id):
        """处理评论内容"""
        user = request.user
        # 校验数据
        if not order_id:
            return redirect(reverse('user:order'))

        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user)
        except OrderInfo.DoesNotExist:
            return redirect(reverse("user:order"))

        # 获取评论条数
        total_count = request.POST.get("total_count")
        total_count = int(total_count)

        # 循环获取订单中商品的评论内容
        for i in range(1, total_count + 1):
            # 获取评论的商品的id
            sku_id = request.POST.get("sku_%d" % i) # sku_1 sku_2
            # 获取评论的商品的内容
            content = request.POST.get('content_%d' % i, '') # cotent_1 content_2 content_3
            try:
                order_goods = OrderGoods.objects.get(order=order, sku_id=sku_id)
            except OrderGoods.DoesNotExist:
                continue

            order_goods.comment = content
            order_goods.save()

        order.order_status = 5 # 已完成
        order.save()

        return redirect(reverse("user:order", kwargs={"page": 1}))

评论后商品详情

在这里插入图片描述
点击商品介绍或者评论 按钮,另一个移除

<script type="text/javascript">
        $('#tag_detail').click(function () {
            $('#tag_comment').removeClass('active')
            $(this).addClass('active')
            $('#tab_detail').show()
            $('#tab_comment').hide()
        })

        $('#tag_comment').click(function () {
            $('#tag_detail').removeClass('active')
            $(this).addClass('active')
            $('#tab_detail').hide()
            $('#tab_comment').show()
        })
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值