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':'删除成功'})
django-购物车添加的更多相关文章
- AI学习吧-购物车-添加商品接口
create接口流程 需求:向购物车添加商品 流程:写shopping_cart路由--->写ShoppingCart视图函数--->使用Authuser校验用户是否登录--->首先 ...
- django中添加用户
在django中添加用户,直接在auth_user表中添加会有问题,因为这里密码是加密的,可以通过manage.py shell加入 创建User: 1 >>> from djang ...
- django项目添加路由----返回给客户端内容-----windows中的python
django项目添加路由 url函数的第一个参数是匹配url路径的正则表达式,第2个参数是路由函数 第一个正则表达式是r'^$',其中r表示正则表达式字符串不对转义符进行转义.“^”表示匹配URL路径 ...
- Django 购物车模板
url from django.contrib import admin from django.urls import path, re_path from django.urls import i ...
- django通过添加session来保存公共变量
有时候我们需要所有页面都使用同一个变量,比如用户登录信息.那不可能render每一个页面时都去传递一个变量,会非常麻烦 而用session可以解决这个问题 web的session可以通过reque ...
- django中添加新的filter
给模板传递了一个字典,却发现无法在模板中直接通过key获得value. 查阅资料后,这个问题可以通过添加自定义的filter来解决. 首先在app目录下创建一个templatetags目录,并在它的下 ...
- django admin 添加用户出现外键约束错误
今天在做mxonline项目时,注册了用户表进admin后,想在后台添加一个用户试试,结果出现了错误,经过一番搜索发现以下两个解决方法,不过我只用了一种 报错信息: IntegrityError: ( ...
- 给Django Admin添加验证码和多次登录尝试限制
Django自带的Admin很好用,但是放到生产环境总还差了点什么= = 看看admin的介绍: Django奉行Python的内置电池哲学.它自带了一系列在Web开发中用于解决常见问题或需求的额外的 ...
- Django中添加富文本编辑器
使用的是CKeditor这个模块 1.安装: pip install django-ckeditor 2.将ckeditor注册到settings.py文件中, 并添加ckeditor的url到你项目 ...
- 关于购物车添加按钮的动画(vue.js)
来自:https://segmentfault.com/a/1190000009294321 (侵删) git 源码地址 https://github.com/ustbhuangyi/vue-sel ...
随机推荐
- SQL2014做数据库主从镜像备份(也可以用于高可用)备忘(非域控)。
部份内容参考原始文章链接:https://www.cnblogs.com/stragon/p/5643754.html ,同时比较有参考价值的文章:https://blog.csdn.net/sqls ...
- JAVA知识点总结篇(三)
抽象类 使用规则 abstract定义抽象类: abstract定义抽象方法,只有声明,不需要实现: 包含抽象方法的类是抽象类: 抽象类中可以包含普通方法,也可以没有抽象方法: 抽象类不能直接创建,可 ...
- php GD 和图像处理函数, 制作一张图片
php GD 和图像处理函数, 制作一张图片 // GD 和图像处理函数 // https://www.php.net/manual/zh/ref.image.php // https://www.p ...
- cas sso 单点登录
一些介绍: https://www.jianshu.com/p/b7de8e4cf217 https://blog.csdn.net/javaloveiphone/article/details/52 ...
- drf中的各种view,viewset
drf中的各种view,viewset Django REST framework里有各种各样的view,让我有点蒙,得好好捋一捋这关系. 视图的作用 Django用"视图"这个概 ...
- python小作业
目录 1.简述变量命名规范 2.name = input(">>>") name变量是什么数据类型通过代码检测 3.if条件语句的基本结构? 4.用print打印 ...
- kali之HexorBase数据库破解
HexorBase 用户名密码连接数据库 暴力破解 点击底栏 Bruteforces Databases Servers , 然后会弹出一个新界面 Databases Bruteforces 新界面 ...
- ps 修补工具
最近刚好遇到需要p图去除水印,这里将ps去除水印的使用记录下来已备翻阅 1.需求图片(如下),使用软件 photo shop cc 2017(以下简称ps) 2.操作 2.1方法一 使用五点修复画笔工 ...
- scrapy爬虫中间件-urlLength
浏览器里面能输入的最大url是有限制的 safari 最多 一万多 ie最少 2083 urllength中间件源码 谷歌和火狐正常 八千多 """ Url Lengt ...
- idea上maven打包
首先要实现maven打包,pom需要引入依赖 pom.xml <project> <dependencies> …… </dependencies> <bui ...