• DJANGO-天天生鲜项目从0到1-009-购物车-Ajax实现添加至购物车功能


    实现功能为:

    在商品详情页面,选择想要购买的数量,点击“加入购物车”按钮,实现右上角的购物车数量增加,并且页面其他信息保持不变。

    一般处理按钮点击后,需要重新查询刷新整个页面的信息,但是很多需求只是刷新局部或一小部分信息,因此可以通过发送Ajax请求实现,注意ajax请求都是在后台运行的,前台不会展示运行的过程。

    Ajax请求过程为:

    1. 前端页面发起ajax请求(这里使用jQuery)将数据传递给后端

    2. 后端执行请求地址相对应的视图函数,返回json内容

    3. ajax执行相应的回调函数。接收返回的json数据并执行后续操作

    编辑详情页面的前端js代码

    1、jQuery获取标签元素对象为:$('.classname')

    2、获取子标签:$('.classname').children('标签名')

    3、获取文本内容为:.text()

    4、获取值属性为:.val()

    5、设置标签值为在获取值的方法中加入参数,该参数就是想要设置成为的值

    6、注意点击事件如果想要调用其他的方法,不能直接写成.click(function_name()),还是得写成.click(function (){function_name()}),即在匿名方法中再调用其他的方法

    7、isNaN() 函数可用于判断其参数是否是 NaN,该值表示一个非法的数字。

    8、发起Ajax请求写法,$.post('/cart/add/', parameter, function(data){....}) 第一个参数为请求提交的地址,第二个参数为传给后台的数据,第三个参数为回调函数,即后台处理完成后,会调用这个回调函数,参数data为后台返回的数据,在回调函数中,使用返回的数据重新设置页面的部分数据

    {% block endfiles %}
    <div class="add_jump"></div>
    
    <script type="text/javascript" src="{% static 'js/jquery-1.12.4.min.js'%}"></script>
    <script type="text/javascript">
    //计算总价
    update_goods_amout()
    function update_goods_amout(){
        //获取单价
        price = $('.show_pirze').children('em').text()
        //获取数量
        count = $('.num_show').val()
        //计算总价
        amount = price * count
            //刷新界面总价
            $('.total').children('em').text(amount.toFixed(2)+'元')
    }
    //加号点击事件
    $('.add').click(function(){
        calculate(1)
    })
    //减号点击事件
    $('.minus').click(function(){
        calculate(-1)
    })
    //加减数量
    function calculate(num){
        //获取原数量
        count = $('.num_show').val()
        //+-1
        count = parseInt(count) + num
        if (count <=0){
            count = 1
        }
        //刷新界面
        $('.num_show').val(count)
        //更新总价
        update_goods_amout()
    }
    //手动输入商品数量
    $('.num_show').blur(function(){
        //获取数量
        count = $(this).val()
        //校验数量,
        if (isNaN(count) || count.trim().length==0 || parseInt(count) <=0){
            //刷新数量
            count = 1
            $(this).val(parseInt(count))
        }
        //更新总价
        update_goods_amout()
    })
    //获取add_cart div元素左上角的坐标
    var $add_x = $('#add_cart').offset().top;
    var $add_y = $('#add_cart').offset().left;
    //获取show_count div元素左上角的坐标
    var $to_x = $('#show_count').offset().top;
    var $to_y = $('#show_count').offset().left;
    
    //点击加入购物车的click事件
    $('#add_cart').click(function(){
        //获取数量
        count = $('.num_show').val()
        //获取商品ID,手动给加入购物车按钮新增一个属性goods_id
        goods_id = $(this).attr('goods_id')
        //csrf验证信息
        csrf = $('input[name="csrfmiddlewaretoken"]').val()
        //组织参数
        parameter = {
            'goods_id': goods_id,
            'count': count,
            'csrfmiddlewaretoken': csrf
        }
        //发起Ajax请求,第三个参数function为回调函数
        $.post('/cart/add/', parameter, function(data){
            if (data.status == 'S'){
                //添加成功
                //购物车加入成功的动态效果
                $(".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.cart_count);
                            });
                    });
                }
            else{
                //添加失败
                alert(data.errmsg)
            }
        })
    })
    
    </script>
    {% endblock endfiles %}

    编辑请求提交的URL

    编辑cart应用的urls.py文件

    from django.urls import path
    from .views import CartView, CartAddView
    
    urlpatterns = [
        path('add/', CartAddView.as_view(), name='add'),
        path('', CartView.as_view(), name='cart'),
    ]

    编辑处理请求的类视图

    编辑cart应用的view.py文件

    1、这里判断用户是否登录时,是手动写的校验,而不是像user应用中继承LoginRequiredMixin,原因是因为如果继承了LoginRequiredMixin,谷歌浏览器按F12打开后台运行情况查看,后台确实会访问重定向到的登录页面,但是由于这里提交的是Ajax请求,前台并不会跳转成登录页面,所以用户体验来说是这个跳转是无效的。

    2、获取前台传过来的商品和数量,校验成功后,将其添加至购物车redis数据库中,然后返回新的购物车数据

    3、返回的是JsonResponse对象,返回值内容为json格式

    from django.views.generic import View
    from django.http import JsonResponse
    from goods.models import Goods
    from django_redis import get_redis_connection
    
    class CartAddView(View):
        '''加入购物车处理视图'''
        def post(self, request):
            user = request.user
            context = {
                'status': 'E',
                'errmsg': ''
            }
            # 判断是否登录
            if not user.is_authenticated:
                context['errmsg'] = '用户未登录!'
                return JsonResponse(context)
    
            # 接收数据
            goods_id = request.POST.get('goods_id')
            count = request.POST.get('count')
    
            # 校验数据
            # 数据是否完整
            if not all([goods_id, count]):
                context['errmsg'] = '数据不完整!'
                return JsonResponse(context)
            # 商品是否存在
            try:
                goods_id = int(goods_id)
                goods = Goods.objects.get(id=goods_id)
            except Exception as e:
                context['errmsg'] = '用户未登录!'
                return JsonResponse(context)
            # 数量格式是否正确
            try:
                count = int(count)
            except Exception as e:
                context['errmsg'] = '商品数量格式不正确!'
                return JsonResponse(context)
    
            # 逻辑处理:添加购物车
            # 连接redis
            connect = get_redis_connection('default')
            cart = 'cart_%d'%(user.id)
            # 获取原购物车中goods_id的数量
            old_count = connect.hget(cart, goods_id)
            if old_count:
                count += int(old_count)
            # 判断是否超过库存
            if count > goods.onhand:
                context['errmsg'] = '超出库存数量!'
                return JsonResponse(context)
            # 将新数量保存至数据库
            connect.hset(cart, goods_id, count)
            # 获取新购物车数量
            cart_count = connect.hlen(cart)
    
            # 返回数据
            context['status'] = 'S'
            context['cart_count'] = cart_count
            return JsonResponse(context)
  • 相关阅读:
    laravel 控制器方法里存get值 和 blade 模板获得闪存值的方法
    获取对象中的值的方法
    python3 语法小结
    集合一些方法陷阱
    文件的读写操作
    字符编码
    数字,字符串,列表,元祖,字典,集合类型内置方法
    if判断,while循环,for循环
    交互,格式化输出,运算符,解压缩!
    python基础知识
  • 原文地址:https://www.cnblogs.com/gcxblogs/p/12824037.html
Copyright © 2020-2023  润新知