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,csrfmiddlewaretoken:csrf}
        // 设置ajax请求为同步
        $.ajaxSettings.async = false
        // 发起ajax post请求,访问/cart/update,传递参数:sku_id count
        // 默认发起的ajax请求都是异步的,不会等回调函数执行
        $.post(/cart/update,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,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,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,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,message:删除成功})

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Python中的函数(二) 在上一篇文章中提到了Python中函数的定义和使用,在这篇文章里我们来讨论下关于函数的一些更深的话题。在学习C语言函数的时候,遇到的问题主要有形参实参的区别、参数的传递和改变、变量的作用域。同样在Python中,关于对函数的理解和使用也存在这些问题。下面来逐一讲解。一.函
Python中的字符串 可能大多数人在学习C语言的时候,最先接触的数据类型就是字符串,因为大多教程都是以&quot;Hello world&quot;这个程序作为入门程序,这个程序中要打印的&quot;Hello world&quot;就是字符串。如果你做过自然语言处理方面的研究,并且用Python
Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程。下面就来了解一下如何在Python中进行对象编程。一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法。 类是对现实世界中一些事物的封装,
Python面向对象编程(二) 在前面一篇文章中谈到了类的基本定义和使用方法,这只体现了面向对象编程的三大特点之一:封装。下面就来了解一下另外两大特征:继承和多态。 在Python中,如果需要的话,可以让一个类去继承一个类,被继承的类称为父类或者超类、也可以称作基类,继承的类称为子类。并且Pytho
Python中的函数(一) 接触过C语言的朋友对函数这个词肯定非常熟悉,无论在哪门编程语言当中,函数(当然在某些语言里称作方法,意义是相同的)都扮演着至关重要的角色。今天就来了解一下Python中的函数用法。一.函数的定义 在某些编程语言当中,函数声明和函数定义是区分开的(在这些编程语言当中函数声明
在windows下如何快速搭建web.py开发框架 用Python进行web开发的话有很多框架供选择,比如最出名的Django,tornado等,除了这些框架之外,有一个轻量级的框架使用起来也是非常方便和顺手,就是web.py。它由一名黑客所创建,但是不幸的是这位创建者于2013年自杀了。据说现在由
将Sublime Text 2搭建成一个好用的IDE 说起编辑器,可能大部分人要推荐的是Vim和Emacs,本人用过Vim,功能确实强大,但是不是很习惯,之前一直有朋友推荐SUblime Text 2这款编辑器,然后这段时间就试了一下,就深深地喜欢上这款编辑器了...
Python中的模块 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句&quot;#include&lt;math.h&gt;&quot;引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?在Python中
Python的基础语法 在对Python有了基础的认识之后,下面来了解一下Python的基础语法,看看它和C语言、java之间的基础语法差异。一.变量、表达式和语句 Python中的语句也称作命令,比如print &quot;hello python&quot;这就是一条语句。 表达式,顾名思义,是
Eclipse+PyDevʽjango+Mysql搭建Python web开发环境 Python的web框架有很多,目前主流的有Django、Tornado、Web.py等,最流行的要属Django了,也是被大家最看好的框架之一。下面就来讲讲如何搭建Django的开发环境。一.准备工作 需要下载的
在windows下安装配置Ulipad 今天推荐一款轻便的文本编辑器Ulipad,用来写一些小的Python脚本非常方便。 Ulipad下载地址: https://github.com/limodou/ulipad http://files.cnblogs.com/dolphin0520/u...
Python中的函数(三) 在前面两篇文章中已经探讨了函数的一些相关用法,下面一起来了解一下函数参数类型的问题。在C语言中,调用函数时必须依照函数定义时的参数个数以及类型来传递参数,否则将会发生错误,这个是严格进行规定的。然而在Python中函数参数定义和传递的方式相比而言就灵活多了。一.函数参数的
在Notepad++中搭配Python开发环境 Python在最近几年一度成为最流行的语言之一,不仅仅是因为它简洁明了,更在于它的功能之强大。它不仅能够完成一般脚本语言所能做的事情,还能很方便快捷地进行大规模的项目开发。在学习Python之前我们来看一下Python的历史由来,&quot;Pytho
Python中的条件选择和循环语句 同C语言、Java一样,Python中也存在条件选择和循环语句,其风格和C语言、java的很类似,但是在写法和用法上还是有一些区别。今天就让我们一起来了解一下。一.条件选择语句 Python中条件选择语句的关键字为:if 、elif 、else这三个。其基本形式如
关于raw_input( )和sys.stdin.readline( )的区别 之前一直认为用raw_input( )和sys.stdin.readline( )来获取输入的效果完全相同,但是最近在写程序时有类似这样一段代码:import sysline = sys.stdin.readline()
初识Python 跟学习所有的编程语言一样,首先得了解这门语言的编程风格和最基础的语法。下面就让我们一起来了解一下Python的编程风格。1.逻辑行与物理行 在Python中有逻辑行和物理行这个概念,物理行是指在编辑器中实际看到的一行,逻辑行是指一条Python语句。在Python中提倡一个物理行只
当我们的代码是有访问网络相关的操作时,比如http请求或者访问远程数据库,经常可能会发生一些错误,有些错误可能重新去发送请求就会成功,本文分析常见可能需要重试的场景,并最后给出python代码实现。
1.经典迭代器 2.将Sentence中的__iter__改成生成器函数 改成生成器后用法不变,但更加简洁。 3.惰性实现 当列表比较大,占内存较大时,我们可以采用惰性实现,每次只读取一个元素到内存。 或者使用更简洁的生成器表达式 4.yield from itertools模块含有大量生成器函数可
本文介绍简单介绍socket的常用函数,并以python-kafka中的源码socketpair为例,来讲解python socket的运用
python实践中经常出现编码相关的异常,大多网上找资料而没有理解原理,导致一次次重复错误。本文对常用Unicode、UTF-8、GB2312编码的原理进行介绍,接着介绍了python字符类型unicode和str以及常见编解码错误UnicodeEncodeError和UnicodeDEcodeEr