django项目-电商平台(4)-购物车模块

介绍

购物车模块是我第一次遇到的这样的情况,购物车其实是将商品与用户进行多对多连接的一个中间环节。人对购物车是一对多,购物车对商品也是一对多,这样就实现了商品与人的多对多。(第一次接触多对多的关系)。另外购物车实现了商品与人关系的暂时储存,提交订单后要清空购物车。

1. model类的建立

这里的一个cart对象,并不是现实生活中的 购物车 ,一个cart对象相当于一个购物车 中的一个商品格子,储存了一种商品和商品的所有者,及商品的数量。所有的cart组成一个用户的购物车。

#用户 与 商品的 联系 是多对多的
#购物车 充当中间 环节,与 用户 一对多,同时 与 商品一对多

class Cart(models.Model):
    user = models.ForeignKey('df_user.User')
    goods = models.ForeignKey('df_goods.GoodInfo')
    count = models.IntegerField()

2. 视图函数

1.购物车显示页面
这个页面就是根据用户获取所有的cart对象,传入模板,然后提取出商品信息和数量并加载

@user_decorator.login
def cart(request):
    uid = request.session.get('uid')
    carts = Cart.objects.filter(user_id=uid)

    context = {'title': '购物车',
               'name': 1,
               'carts': carts}
    return render(request, 'df_cart/cart.html', context)

2.加入购物车的视图函数
在模板中加入购物车的视图函数是通过ajax异步发送的,这样的化需要返回json格式的数据。传入参数为商品id和数量

@user_decorator.login
def add(request,gid,gcount):
    gid = int(gid)
    gcount = int(gcount)
    uid = request.session.get('uid')
    carts = Cart.objects.filter(goods_id=gid,user_id=uid)
    #先判断 该用户 购物车中 是否 存在 该商品
    #如果纯在,则仅作数量上的 加法
    if len(carts) >= 1:
        cart = carts[0]
        cart.count += gcount
    else:
        cart = Cart()
        cart.user_id = uid
        cart.goods_id =gid
        cart.count =gcount
    cart.save()
    #判断请求方式 是否是ajax,若是则返回json格式的 商品数量即可
    if request.is_ajax():
        count = Cart.objects.filter(user_id=uid).count()
        return JsonResponse({'count':count})
    else:
        return  redirect('/cart')

3.接下来是编辑购物车信息的请求函数
同样编辑购物车中的商品,数量信息也是通过ajax来异步请求的

def edit(request,cid,gcount):#传入 cart id 和 count 改变Cart
    try:
        cart = Cart.objects.get(pk=int(cid))
        cart.count = int(gcount)
        cart.save()
    except:
        return JsonResponse({'count':gcount})
        #如果错误就将原来的数量返回去

    return JsonResponse({'count':0})

4.最后是删除一行 购物车中的商品的 请求函数
直接做物理删除

def delete(request,cid):
    try:
        cart=Cart.objects.get(pk=int(cid))
        cart.delete()
        data ={'ok':1}
    except:
        data={'ok':0}
    return JsonResponse(data)

3. 模板和js

购物车是用到js最多的地方,商品数量的加减,加入购物车,顶部购物车显示商品类别数量,小计与总计,从页面上删除一行商品。

1.购物车显示页面的js

<script>

$(function () {
    total();
    {#    全选全消#}
    $('#check_all').click(function () {
{#        获取当前全选框的状态#}

        state=$(this).prop('checked');
{#        将其他的选矿 都设置成这个状态#}
        $(':checkbox:not(#ckeck_all)').prop('checked',state)
    });
    //选择
    $(':checkbox:not(#check_all)').click(function () {
        if($(this).prop('checked')){
            alert($(':checked').length)
            if($(':checked').length+1==$(':checkbox').length
            ){  $('#ckeck_all').prop('checked',true)

            }

        }
        else{
            $('#check_all').prop('checked',false)
        }
    });

    //数量加
    //为所有的 add绑定点击事件
    $('.add').click(function () {

        txt=$(this).next();
        //数值加1,同时取消 焦点
        txt.val(parseFloat(txt.val())+1).blur()

    });
     $('.minus').click(function () {
        txt=$(this).prev();
        //数值加1,同时取消 焦点
        txt.val(parseFloat(txt.val())-1).blur()

    });
    //在blur事件里ajax 提交
    $('.num_show').blur(function () {
        count=$(this).val();
        if(count<=0){
            alert('数量不能小于0');
            return
        }else {};

        id = $(this).parents('.cart_list_td').attr('id');

        $.get('/cart/edit_'+id+'_'+count,function (data) {
            if(data.count==0){
                //修改成功,计算总价
                alert('ok')
                total();
            }
            else {
                //修改失败,改为原来 的值(回掉回来原来的值)
                $(this).val(data.count)
            }


        })

    })


})
function cart_del(cart_id) {
        del = confirm('确定删除');
        if(del){
            $.get('/cart/delete/'+cart_id,function (data) {
                if(data.ok==1){
                    //删掉哪一行 商品
                    $('ul').remove('#'+cart_id);
                    total();
                }


            })
        }

    }
function total(){
    total1=0;
    total_count=0;

        $('.col07').each(
            function () {

            //获取数量
            count=$(this).prev().find('input').val();
            //获取单价
            price = $(this).prev().prev().text();
            //计算小计
            total0=parseFloat(count)*parseFloat(price);
            //显示小计
            $(this).text(total0.toFixed(2));
            //加到总计上
            total1 += total0;
            total_count++;



        });
        //显示总计
        $('#total').text(total1.toFixed(2));
        $('.total_count1').text(total_count);
    }
function go_order() {
    s = '';
    $(':checked:not(#check_all)').each(function () {
         id = $(this).parents('.cart_list_td').attr('id');

         s = s +'cart_id='+id + '&'

    })

    //删掉最后一个&

    s=s.substring(0,s.length-1);
    alert(s);
    location.href = '/order?'+s ;

    }

    </script>

2.详情页加入购物车的js
里面的动画效果看不懂,但是主要请求看懂就行了

<script type="text/javascript">
        var $add_x = $('#add_cart').offset().top;
        var $add_y = $('#add_cart').offset().left;

        var $to_x = $('#show_count').offset().top;
        var $to_y = $('#show_count').offset().left;

        $(".add_jump").css({'left':$add_y+80,'top':$add_x+10,'display':'block'})
        $('#add_cart').click(function() {
            {#          先判断是否登录#}
{#            alert('点击');#}
            if ($('.login_btn fl').text().indexOf('登录') >= 0) {
                alert('请登陆后购买');
                location.href('/user/login')
                return

            };

{#                alert('ok');#}
                $(".add_jump").stop().animate({
                        'left': $to_y + 7,
                        'top': $to_x + 7
                    },
                    "fast", function () {
                        $(".add_jump").fadeOut('fast', function () {

                            count =$('.num_show').val();

                            $.get('/cart/add_{{ goods.id }}_'+count.toString(),function (data) {


                                 $('#show_count').html(data.count);
                            })

                        });

                    });

        })
    </script>

购物车基本完成了,收获很大,下一个是订单模块。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容