当前位置: 首页 > news >正文

17.2 修改购物车商品

17.2 修改购物车商品

问题分析

  1. 同样要分为登录和未登录两种状态分别处理。
  2. 要处理商品数据的变化及勾选状态的变化,还有商品总金额的变化 (在前端实现)。
  3. 若已登录,则需要覆盖redis中的数据。若未登录,则需要覆盖COOKIE中的数据。

设计

因只是对购物车中的商品数据进行修改,所以请求方式为put。

需要更新的数据为sku_id,count , selected几个参数。

实现

在carts应用下定义constants.py,存放常量

CARTS_COOKIE_EXPIRES = 3600 * 24 * 14  # 两周

carts应用下views.py中增加put方法,修改后的全部代码如下

import base64
import json
import picklefrom django.conf import settings
from django.http import HttpResponseForbidden, JsonResponse
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connectionfrom carts import constants
from goods.models import SKU
from xiaoyu_mall_new.utils.response_code import RETCODEclass CartsView(View):def put(self, request):# 接收参数json_dict = json.loads(request.body.decode())sku_id = json_dict.get('sku_id')count = json_dict.get('count')selected = json_dict.get('selected')# 校验参数if not all([sku_id, count]):return HttpResponseForbidden('缺少必须的参数')try:sku = SKU.objects.get(id=sku_id)except SKU.DoesNotExist:return HttpResponseForbidden('商品sku_id不存在')try:count = int(count)except Exception:return HttpResponseForbidden('参数count有误')if selected:if not isinstance(selected, bool):return HttpResponseForbidden('参数selected 有误')user = request.userif user.is_authenticated:# 登录状态redis_conn = get_redis_connection('carts')pl = redis_conn.pipeline()pl.hset('carts_%s' % user.id, sku_id)if selected:pl.sadd('selected_%s' % user.id, sku_id)else:pl.srem('selected_%s' % user.id, sku_id)pl.execute()# 创建响应cart_sku = {'id': sku_id,'count': count,'selected': selected,'name': sku.name,'price': sku.price,'amount': sku.price * count,'stock': sku.stock,'default_image_url': settings.STATIC_URL + 'images/goods/' + sku.default_image.url + '.jpg',}return JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车成功', 'cart_sku': cart_sku})else:# 未登录 状态cart_str = request.COOKIES.get('carts')if cart_str:cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))else:cart_dict = {}cart_dict[sku_id] = {'count': count,'selected': selected}cookie_cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()cart_sku = {'id': sku_id,'count': count,'selected': selected,'name': sku.name,'price': sku.price,'amount': sku.price * count,'stock': sku.stock,'default_image_url': settings.STATIC_URL + 'images/goods/' + sku.default_image.url + '.jpg',}response = JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车成功', 'cart_sku': cart_sku})response.set_cookie('carts', cookie_cart_str, max_age=constants.CARTS_COOKIE_EXPIRES)return responsedef get(self, request):# 判断用户是否登录user = request.userif user.is_authenticated:# 创建连接到redis的对象redis_conn = get_redis_connection('carts')# 查询user_id、count与sku_id构成的购物车记录redis_cart = redis_conn.hgetall('carts_%s' % user.id)# 查询勾选的商品smembers 命令返回集合中的所有的成员redis_selected = redis_conn.smembers('selected_%s' % user.id)cart_dict = {}for sku_id, count in redis_cart.items():cart_dict[int(sku_id)] = {"count": int(count),"selected": sku_id in redis_selected}else:# 用户未登录,查询cookies购物车cart_str = request.COOKIES.get('carts')if cart_str:# 对 cart_str进行编码,获取字节类型的数据cart_str_bytes = cart_str.encode()# 对cart_str_bytes进行解码,获取明文数据cart_dict_bytes = base64.b64decode(cart_str_bytes)# 对cart_dict_bytes反序列化,转换成Python能识别的字典类型的数据cart_dict = pickle.loads(cart_dict_bytes)else:cart_dict = {}# 构造响应数据sku_ids = cart_dict.keys()# 一次性查询出所有的skusskus = SKU.objects.filter(id__in=sku_ids)cart_skus = []for sku in skus:cart_skus.append({'id': sku.id,'count': cart_dict.get(sku.id).get('count'),# 将True,转'True',方便json解析'selected': str(cart_dict.get(sku.id).get('selected')),'name': sku.name,'default_image_url': settings.STATIC_URL +'images/goods/' + sku.default_image.url + '.jpg','price': str(sku.price),'amount': str(sku.price * cart_dict.get(sku.id).get('count')),'stock': sku.stock})context = {'cart_skus': cart_skus}# 渲染购物车页面return render(request, 'cart.html', context)def post(self, request):# 将JSON格式的字符串反序列化为Python对象json_dict = json.loads(request.body.decode())# 接收参数sku_id = json_dict.get('sku_id')count = json_dict.get('count')selected = json_dict.get('selected', True)# 校验参数if not all([sku_id, count]):return HttpResponseForbidden('缺少必要参数')# 校验sku_id参数try:SKU.objects.get(id=sku_id)except SKU.DoesNotExist:return HttpResponseForbidden('参数sku_id错误')# 校验count参数try:count = int(count)except Exception:return HttpResponseForbidden('参数count错误')# 校验selected参数if selected:if not isinstance(selected, bool):return HttpResponseForbidden('参数selected错误')# 判断用户是否登录user = request.user# 已登录,数据格式为:# carts_user_id:{sku_id1:count1,sku_id2:count2,...}# selected_user_id:{sku_id1,sku_id2,...}if user.is_authenticated:redis_conn = get_redis_connection('carts')# 创建管道,用于执行多个命令pl = redis_conn.pipeline()# 以增量形式保存商品数据# - 'carts_%s' % user.id :生成以用户ID为后缀的购物车键名(如 carts_123 )# - sku_id :商品SKU的唯一标识,作为哈希表的字段名# - count :要增加的数量(可为正数或负数)pl.hincrby('carts_%s' % user.id, sku_id, count)# 保存商品的勾选状态if selected:# 若selected为True,将sku_id添加到selected集合中pl.sadd('selected_%s' % user.id, sku_id)# 执行管道命令pl.execute()return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})else:  # 未登录,购物车数据存储在cookie中,数据结构如下# cart_dict = {#     'sku_id1': {'count': 5, 'selected': 'True'},#     'sku_id2': {'count': 3, 'selected': 'False'}# ...# }cart_str = request.COOKIES.get('carts')# 若购物车数据存在,将其反序列化为字典if cart_str:# 对cart_str进行编码,获取字节类型数据cart_str_bytes = cart_str.encode()# 对密文类型数据cart_str_bytes进行base64解码,获取明文数据cart_dict_bytes = base64.b64decode(cart_str_bytes)# 对明文类型数据cart_dict_bytes进行反序列化,获取字典类型数据cart_dict = pickle.loads(cart_dict_bytes)# 若没有数据,创建空字典else:cart_dict = {}# 若购物车数据中已存在该商品,累加数量if sku_id in cart_dict:origin_count = cart_dict[sku_id]['count']count += origin_countcart_dict[sku_id] = {'count': count, 'selected': selected}# 对字典类型数据cart_dict进行序列化,获取字节类型数据cart_dict_bytes = pickle.dumps(cart_dict)# 对字节类型数据cart_dict_bytes进行base64编码,获取密文类型数据cart_str_bytes = base64.b64encode(cart_dict_bytes)# 对密文类型数据cart_str_bytes进行解码,获取明文类型数据cookie_cart_str = cart_str_bytes.decode()response = JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})response.set_cookie('carts', cookie_cart_str)# 响应结果return response

http://www.dtcms.com/a/331808.html

相关文章:

  • RLVR(可验证奖励的强化学习):大模型后训练的客观评估策略
  • 负载因子(Load Factor) :哈希表(Hash Table)中的一个关键性能指标
  • AI大模型+Meta分析:助力发表高水平SCI论文
  • 多任务并发:进程管理的核心奥秘
  • 【记录】Apache SeaTunnel 系统监控信息
  • 使用ETL工具同步Oracle的表到Doris
  • 使用load data或insert导入10w条数据
  • 51单片机-GPIO介绍
  • 网络组播技术详解
  • 深入理解 `std::any`:C++ 中的万能容器
  • 俄罗斯加强互联网管控,限制 WhatsApp 和 Telegram 通话
  • P5663 [CSP-J2019] 加工零件
  • 腾讯K8S环境【TKE】中,如何驱逐指定pod重新部署?
  • Kafka下载和安装
  • Python:如何处理WRF投影(LCC, 兰伯特投影)?
  • 深度学习 --- ResNet神经网络
  • 【递归完全搜索】CCC 2008 - 24点游戏Twenty-four
  • 【完整源码+数据集+部署教程】膝关节屈伸运动检测系统源码和数据集:改进yolo11-RFAConv
  • pip和dnf只下载不安装离线包
  • 沈帅波出席茅台红缨子高粱节探讨产业赋能新模式
  • Ansys FreeFlow入门:对搅拌罐进行建模
  • 【159页PPT】机械制造行业数字化转型某著名企业U8系统全解决方案(附下载方式)
  • Avalonia_SukiUI明暗主题切换时部分元素颜色不变
  • jetson orin nx(8G)烧录super系统实录
  • Ubuntu下载、安装、编译指定版本python
  • 机器学习--KNN算法
  • Linux入门指南:基础开发工具---yum/apt
  • 单北斗GNSS变形监测应用解析
  • 读《精益数据分析》:移情(Empathy)—— 验证真实需求,避免伪需求陷阱
  • 大模型工程化落地:从模型选择到性能优化的实战指南