• django-购物车添加


    商品详情页detail.html添加加入购物车按钮

    <a href="javascript:;" sku_id="{{ sku.id }}" class="add_cart" id="add_cart">加入购物车</a>
    ....
    <script>
    $('#add_cart').click(function(){
                // 获取商品id和商品数量
                sku_id = $(this).attr('sku_id') // attr prop
                count = $('.num_show').val()
                csrf = $('input[name="csrfmiddlewaretoken"]').val()
                // 组织参数
                params = {'sku_id':sku_id, 'count':count, 'csrfmiddlewaretoken':csrf}
                // 发起ajax post请求,访问/cart/add, 传递参数:sku_id count
                $.post('/cart/add', params, function (data) {
                    if (data.res == 5){
                        // 添加成功
                        $(".add_jump").css({'left':$add_y+80,'top':$add_x+10,'display':'block'})
                        $(".add_jump").stop().animate({
                            'left': $to_y+7,
                            'top': $to_x+7},
                            "fast", function() {
                                $(".add_jump").fadeOut('fast',function(){
                                    // 重新设置用户购物车中商品的条目数
                                    $('#show_count').html(data.total_count);
                                });
                        });
                    }
                    else{
                        // 添加失败
                        alert(data.errmsg)
                    }
                })
            })
    </script>

    视图函数views.py中添加add功能

    from django.shortcuts import render
    from django.views.generic import View
    from django.http import JsonResponse
    
    from goods.models import GoodsSKU
    from django_redis import get_redis_connection
    
    # Create your views here.
    # 添加商品到购物车:
    # 1)请求方式,采用ajax post
    # 如果涉及到数据的修改(新增,更新,删除), 采用post
    # 如果只涉及到数据的获取,采用get
    # 2) 传递参数: 商品id(sku_id) 商品数量(count)
    
    
    # ajax发起的请求都在后台,在浏览器中看不到效果
    # /cart/add
    class CartAddView(View):
        '''购物车记录添加'''
        def post(self, request):
            '''购物车记录添加'''
            user = request.user
            if not user.is_authenticated():
                # 用户未登录
                return JsonResponse({'res':0, 'errmsg':'请先登录'})
    
            # 接收数据
            sku_id = request.POST.get('sku_id')
            count = request.POST.get('count')
    
            # 数据校验
            if not all([sku_id, count]):
                return JsonResponse({'res':1, 'errmsg':'数据不完整'})
    
            # 校验添加的商品数量
            try:
                count = int(count)
            except Exception as e:
                # 数目出错
                return JsonResponse({'res':2, 'errmsg':'商品数目出错'})
    
            # 校验商品是否存在
            try:
                sku = GoodsSKU.objects.get(id=sku_id)
            except GoodsSKU.DoesNotExist:
                # 商品不存在
                return JsonResponse({'res':3, 'errmsg':'商品不存在'})
    
            # 业务处理:添加购物车记录
            conn = get_redis_connection('default')
            cart_key = 'cart_%d'%user.id
            # 先尝试获取sku_id的值 -> hget cart_key 属性
            # 如果sku_id在hash中不存在,hget返回None
            cart_count = conn.hget(cart_key, sku_id)
            if cart_count:
                # 累加购物车中商品的数目
                count += int(cart_count)
    
            # 校验商品的库存
            if count > sku.stock:
                return JsonResponse({'res':4, 'errmsg':'商品库存不足'})
    
            # 设置hash中sku_id对应的值
            # hset->如果sku_id已经存在,更新数据, 如果sku_id不存在,添加数据
            conn.hset(cart_key, sku_id, count)
    
            # 计算用户购物车商品的条目数
            total_count = conn.hlen(cart_key)
    
            # 返回应答
            return JsonResponse({'res':5, 'total_count':total_count, 'message':'添加成功'})

    购物车页面

    跳转到购物车

    base.html中

     <a href="{% url 'cart:show' %}" class="cart_name fl">我的购物车</a>

    视图函数views.py添加CartInfoView视图功能

    # /cart/
    from utils.mixin import LoginRequiredMinxin  # 登录校验
    class CartInfoView(LoginRequiredMinxin, View):
        '''购物车页面显示'''
        def get(self, request):
            '''显示'''
            # 获取登录的用户
            user = request.user
            # 获取用户购物车中商品的信息
            conn = get_redis_connection('default')
            cart_key = 'cart_%d'%user.id
            # {'商品id':商品数量, ...}
            cart_dict = conn.hgetall(cart_key)
    
            skus = []
            # 保存用户购物车中商品的总数目和总价格
            total_count = 0
            total_price = 0
            # 遍历获取商品的信息
            for sku_id, count in cart_dict.items():
                # 根据商品的id获取商品的信息
                sku = GoodsSKU.objects.get(id=sku_id)
                # 计算商品的小计
                amount = sku.price*int(count)
                # 动态给sku对象增加一个属性amount, 保存商品的小计
                sku.amount = amount
                # 动态给sku对象增加一个属性count, 保存购物车中对应商品的数量
                sku.count = count
                # 添加
                skus.append(sku)
    
                # 累加计算商品的总数目和总价格
                total_count += int(count)
                total_price += amount
    
            # 组织上下文
            context = {'total_count':total_count,
                       'total_price':total_price,
                       'skus':skus}
    
            # 使用模板
            return render(request, 'cart.html', context)

    模板cart.html

    {% extends 'layout/base_no_cart.html' %}
    {% load staticfiles %}
    {% block title %}天天生鲜-购物车{% endblock title %}
    {% block page_title %}购物车{% endblock page_title %}
    {% block body %}
        <div class="total_count">全部商品<em>{{ total_count }}</em></div>
        <ul class="cart_list_th clearfix">
            <li class="col01">商品名称</li>
            <li class="col02">商品单位</li>
            <li class="col03">商品价格</li>
            <li class="col04">数量</li>
            <li class="col05">小计</li>
            <li class="col06">操作</li>
        </ul>
        <form method="post" action="">
        {% 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>
    {% endblock body %}
    
    {% block bottomfiles %}
        <script src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
        <script>
        // 计算被选中的商品的总件数和总价格
        function update_page_info() {
            // 获取所有被选中的商品的checkbox
            // 获取所有被选中的商品所在的ul元素
            total_count = 0
            total_price = 0
            $('.cart_list_td').find(':checked').parents('ul').each(function () {
                // 获取商品的数目和小计
                count = $(this).find('.num_show').val()
                amount = $(this).children('.col07').text()
                // 累加计算商品的总件数和总价格
                count = parseInt(count)
                amount = parseFloat(amount)
                total_count += count
                total_price += amount
            })
            // 设置被选中的商品的总件数和总价格
            $('.settlements').find('em').text(total_price.toFixed(2))
            $('.settlements').find('b').text(total_count)
        }
    
        // 计算商品的小计
        function update_goods_amount(sku_ul) {
            // 获取商品的价格和数量
            count = sku_ul.find('.num_show').val()
            price = sku_ul.children('.col05').text()
            // 计算商品的小计
            amount = parseInt(count)*parseFloat(price)
            // 设置商品的小计
            sku_ul.children('.col07').text(amount.toFixed(2)+'')
        }
    
        // 商品的全选和全不选
        $('.settlements').find(':checkbox').change(function () {
            // 获取全选的checkbox的选中状态
            is_checked = $(this).prop('checked')
            // 遍历商品的对应的checkbox,设置这些checkbox的选中状态和全选的checkbox保持一致
            $('.cart_list_td').find(':checkbox').each(function () {
                $(this).prop('checked', is_checked)
            })
            // 更新页面的信息
            update_page_info()
        })
    
        // 商品对应的checkbox状态发生改变时,设置全选checkbox的状态
        $('.cart_list_td').find(':checkbox').change(function () {
            // 获取页面上所有商品的数目
            all_len = $('.cart_list_td').length
            // 获取页面上被选中的商品的数目
            checked_len = $('.cart_list_td').find(':checked').length
            is_checked = true
            if (checked_len < all_len){
                is_checked = false
            }
            $('.settlements').find(':checkbox').prop('checked', is_checked)
            // 更新页面的信息
            update_page_info()
        })
    
        // 更新购物车中商品的数量
        error_update = false
        total = 0
        function update_remote_cart_info(sku_id, count) {
            csrf = $('input[name="csrfmiddlewaretoken"]').val()
            // 组织参数
            params = {'sku_id':sku_id, 'count':count, 'csrfmiddlewaretoken':csrf}
            // 设置ajax请求为同步
            $.ajaxSettings.async = false
            // 发起ajax post请求,访问/cart/update, 传递参数:sku_id count
            // 默认发起的ajax请求都是异步的,不会等回调函数执行
            $.post('/cart/update', params, function (data) {
                if (data.res == 5){
                    // 更新成功
                    error_update = false
                    total = data.total_count
                }
                else{
                    // 更新失败
                    error_update = true
                    alert(data.errmsg)
                }
            })
            // 设置ajax请求为异步
            $.ajaxSettings.async = true
        }
    
        // 购物车商品数量的增加
        $('.add').click(function () {
            // 获取商品的id和商品的数量
            sku_id = $(this).next().attr('sku_id')
            count = $(this).next().val()
    
            // 组织参数
            count = parseInt(count)+1
    
            // 更新购物车记录
            update_remote_cart_info(sku_id, count)
    
            // 判断更新是否成功
            if (error_update == false){
                // 重新设置商品的数目
                $(this).next().val(count)
                // 计算商品的小计
                update_goods_amount($(this).parents('ul'))
                // 获取商品对应的checkbox的选中状态,如果被选中,更新页面信息
                is_checked = $(this).parents('ul').find(':checkbox').prop('checked')
                if (is_checked){
                    // 更新页面信息
                    update_page_info()
                }
                // 更新页面上购物车商品的总件数
                $('.total_count').children('em').text(total)
            }
        })
    
        // 购物车商品数量的减少
        $('.minus').click(function () {
            // 获取商品的id和商品的数量
            sku_id = $(this).prev().attr('sku_id')
            count = $(this).prev().val()
    
            // 校验参数
            count = parseInt(count)-1
            if (count <= 0){
                return
            }
    
            // 更新购物车中的记录
            update_remote_cart_info(sku_id, count)
    
            // 判断更新是否成功
            if (error_update == false){
                // 重新设置商品的数目
                $(this).prev().val(count)
                // 计算商品的小计
                update_goods_amount($(this).parents('ul'))
                // 获取商品对应的checkbox的选中状态,如果被选中,更新页面信息
                is_checked = $(this).parents('ul').find(':checkbox').prop('checked')
                if (is_checked){
                    // 更新页面信息
                    update_page_info()
                }
                // 更新页面上购物车商品的总件数
                $('.total_count').children('em').text(total)
            }
        })
    
        // 记录用户输入之前商品的数量
        pre_count = 0
        $('.num_show').focus(function () {
            pre_count = $(this).val()
        })
    
        // 手动输入购物车中的商品数量
        $('.num_show').blur(function () {
            // 获取商品的id和商品的数量
            sku_id = $(this).attr('sku_id')
            count = $(this).val()
    
            // 校验参数
            if (isNaN(count) || count.trim().length==0 || parseInt(count)<=0){
                // 设置商品的数目为用户输入之前的数目
                $(this).val(pre_count)
                return
            }
    
            // 更新购物车中的记录
            count = parseInt(count)
            update_remote_cart_info(sku_id, count)
    
            // 判断更新是否成功
            if (error_update == false){
                // 重新设置商品的数目
                $(this).val(count)
                // 计算商品的小计
                update_goods_amount($(this).parents('ul'))
                // 获取商品对应的checkbox的选中状态,如果被选中,更新页面信息
                is_checked = $(this).parents('ul').find(':checkbox').prop('checked')
                if (is_checked){
                    // 更新页面信息
                    update_page_info()
                }
                // 更新页面上购物车商品的总件数
                $('.total_count').children('em').text(total)
            }
            else{
                // 设置商品的数目为用户输入之前的数目
                $(this).val(pre_count)
            }
        })
    
        // 删除购物车中的记录
        $('.cart_list_td').children('.col08').children('a').click(function () {
            // 获取对应商品的id
            sku_id = $(this).parents('ul').find('.num_show').attr('sku_id')
            csrf = $('input[name="csrfmiddlewaretoken"]').val()
            // 组织参数
            params = {'sku_id':sku_id, 'csrfmiddlewaretoken':csrf}
            // 获取商品所在的ul元素
            sku_ul = $(this).parents('ul')
            // 发起ajax post请求, 访问/cart/delete, 传递参数:sku_id
            $.post('/cart/delete', params, function (data) {
                if (data.res == 3){
                    // 删除成功,异常页面上商品所在的ul元素
                    sku_ul.remove()
                    // 获取sku_ul中商品的选中状态
                    is_checked = sku_ul.find(':checkbox').prop('checked')
                    if (is_checked){
                        // 更新页面信息
                        update_page_info()
                    }
                    // 重新设置页面上购物车中商品的总件数
                    $('.total_count').children('em').text(data.total_count)
                }
                else{
                    alert(data.errmsg)
                }
            })
        })
    
        </script>
    {% endblock bottomfiles %}

    视图函数views.py中添加购物车更新和删除功能

    # 更新购物车记录
    # 采用ajax post请求
    # 前端需要传递的参数:商品id(sku_id) 更新的商品数量(count)
    # /cart/update
    class CartUpdateView(View):
        '''购物车记录更新'''
        def post(self, request):
            '''购物车记录更新'''
            user = request.user
            if not user.is_authenticated():
                # 用户未登录
                return JsonResponse({'res': 0, 'errmsg': '请先登录'})
    
            # 接收数据
            sku_id = request.POST.get('sku_id')
            count = request.POST.get('count')
    
            # 数据校验
            if not all([sku_id, count]):
                return JsonResponse({'res': 1, 'errmsg': '数据不完整'})
    
            # 校验添加的商品数量
            try:
                count = int(count)
            except Exception as e:
                # 数目出错
                return JsonResponse({'res': 2, 'errmsg': '商品数目出错'})
    
            # 校验商品是否存在
            try:
                sku = GoodsSKU.objects.get(id=sku_id)
            except GoodsSKU.DoesNotExist:
                # 商品不存在
                return JsonResponse({'res': 3, 'errmsg': '商品不存在'})
    
            # 业务处理:更新购物车记录
            conn = get_redis_connection('default')
            cart_key = 'cart_%d'%user.id
    
            # 校验商品的库存
            if count > sku.stock:
                return JsonResponse({'res':4, 'errmsg':'商品库存不足'})
    
            # 更新
            conn.hset(cart_key, sku_id, count)
    
            # 计算用户购物车中商品的总件数 {'1':5, '2':3}
            total_count = 0
            vals = conn.hvals(cart_key)
            for val in vals:
                total_count += int(val)
    
            # 返回应答
            return JsonResponse({'res':5, 'total_count':total_count, 'message':'更新成功'})
    
    
    # 删除购物车记录
    # 采用ajax post请求
    # 前端需要传递的参数:商品的id(sku_id)
    # /cart/delete
    class CartDeleteView(View):
        '''购物车记录删除'''
        def post(self, request):
            '''购物车记录删除'''
            user = request.user
            if not user.is_authenticated():
                # 用户未登录
                return JsonResponse({'res': 0, 'errmsg': '请先登录'})
    
            # 接收参数
            sku_id = request.POST.get('sku_id')
    
            # 数据的校验
            if not sku_id:
                return JsonResponse({'res':1, 'errmsg':'无效的商品id'})
    
            # 校验商品是否存在
            try:
                sku = GoodsSKU.objects.get(id=sku_id)
            except GoodsSKU.DoesNotExist:
                # 商品不存在
                return JsonResponse({'res':2, 'errmsg':'商品不存在'})
    
            # 业务处理:删除购物车记录
            conn = get_redis_connection('default')
            cart_key = 'cart_%d'%user.id
    
            # 删除 hdel
            conn.hdel(cart_key, sku_id)
    
            # 计算用户购物车中商品的总件数 {'1':5, '2':3}
            total_count = 0
            vals = conn.hvals(cart_key)
            for val in vals:
                total_count += int(val)
    
            # 返回应答
            return JsonResponse({'res':3, 'total_count':total_count, 'message':'删除成功'})
  • 相关阅读:
    Row versus Set Processing, Surprise!(集合处理和单行处理数据的差异性)
    SVN导出增量包的方法
    Number of Digit One
    VPS+LNMP+WordPress搭建个人网站
    寻找最小的k个数(大顶堆方法)
    二叉搜索树转化为有序双向链表(C语言)
    LeetCode 345 Reverse Vowels of a String
    LeetCode 278 First Bad Version
    LeetCode 205 Isomorphic Strings
    LeetCode 88 Merge Sorted Array
  • 原文地址:https://www.cnblogs.com/yifengs/p/11665093.html
Copyright © 2020-2023  润新知