1 购物车的实现问题思路

购物车需求分析:
1 未登陆和已登陆都保存到用户的购物车数据。
2 用户可以对购物车进行增删改查;
3 购物车有选择状态,只有选中的状态才能生成订单;
4 用户登陆时,合并cookie
涉及到技术栈:
1 redis 的hash和set 的操作,增删改查及管道技术
2 cooike 的设置和删除以及解码和加码的
技术实现:
对于未登陆用户,购物车数据使用浏览器cookie保存
对于已登陆的用户,购物车在后端使redis保存,具体存储结果
hash {
使用幂等技术,多次点击完成后,得到最终的数量
数据库redis的设计:
hash: user_id sku_id count
set : sku_id (选中商品)
redis 中管道技术的实现:
1 创建管道实例
2 添加执行操作
3 管道统一执行
Cookie保存数据
涉及的知识点:
1 获取cookie中的card值
car_str=request.COOKIES.get(cart)
2 如果不为空,进行解码, 先进行二进制转换encode,然后base64.b64decode,然后再转换成字典
cart_dict=picker.loads(base64.b64decode(cart_str.encode()))
3 判断sku_id 存在 if sku_id in card_dict,
origin_count=card_dict[sku_id]['count']
count+=origin_count
4 进行更新数据
cart_dict[sku_id]={
'count':count,
'selected':selected
5 进行加密
card=picker.dumps(base64.b64encode(cart_dict.decode()))
6 保存cookie
response.set_cookie('card',card,24*3600 1 #有关cookie 解码和加密写单独函数进行实现

2 购物车的增加

2.1增加业务的思路
逻辑分析
# 1 前端发送增加请求,post请求,获取selected,sku_id ,count
# 2 首先检查商品
# 3 检查是用户是否登陆,
# 3.1 如何登陆,则存储到redis,
# 3.1.1 登陆Redis,
# 使用 redis hash user.id {sku_id:count}
# 使用 redis.con.hset('card_%s'%user.id, sku_id,count)
# 3.1.2 使用 hiscrby进行累计存储
redis.con.hincry('card_%s'%user.id,sku_id,count)
# 3.1.3 如何selected 选中,则,suk_id 存放到set
if selected:
redis.con.sadd('card_seleted_%s'%user.id .sku_id
# 3.2 没有登陆,存储cookie中
# 3.2.1获取cookie 的值
# 3.2.2 不存在,则创建 cart={},
# 3.2.3重新写入cooie 中,返回结果
# 4 返回结果
2.2 代码实现
 def post(self,request):
# 1 前端发送增加请求,post请求,获取selected,sku_id ,count
dict_data=json.loads(request.body.decode())
sku_id=dict_data.get('sku_id')
count=dict_data.get('count')
selected=dict_data.get('selected')
# 2 首先检查商品
if not all([sku_id,count]):
return JsonResponse({'code':401,'errmsg':'传递的参数不全'})
try:
sku=SKU.objects.get(id=sku_id)
except SKU.DoesNotExist:
return JsonResponse({'code':402,'errmsg':'增加到购物车商品不存在'})
# 3 检查是用户是否登陆,
try:
user=request.user
except Exception:
user=None
# 3.1 如何登陆,则存储到redis,
# 3.1.1 登陆Redis,
if user is None and user.is_authenticated:
redis_con = get_redis_connection(CARD_CACHE_ALIAS)
rc_p = redis_con.pipeline() # 购物车中无没有该商品,没有则增加,有则进行累计实现增量
if not rc_p.hexists('cart_%s'%user.id,sku_id):
rc_p.hset('cart_%s'% user.id,sku_id,count) # 3.1.2使用hiscrby进行累计存 储
else:
rc_p.hincrby('cart_%s'%user.id, sku_id, count)
print(rc_p.hincrby('cart_%s'%user.id, sku_id, count))
# 3.1.3 如何select 选中,则,suk_id 存放到set
if selected:
rc_p.sadd('carts_selected_%s'%user.id,sku_id)
# 让管道集中处理
rc_p.execute()
return JsonResponse({'code': 200, 'errmsg': '完成添加'})
# 3.2 没有登陆,存储cookie中
else:
# 1获取cookie 的值
cart_dict=get_cookie_key(request,'cart')
# cart_str = request.COOKIES.get('cart')
# #2 判断是否为空,为空
# if cart_str is not None:
# cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
# else:
# cart_dict={}
if sku_id in cart_dict:
origin_count=cart_dict[sku_id]['count']
count+=origin_count
cart_dict[sku_id]={
'count':count,
'selected':selected
}
response=up_cookie_key('cart',cart_dict) return response
# 4 返回结果

3 购物车的查询

3.1购物车查询的思路分析:
       # 1  获取get请求,先判断是否为登陆客户
# 2 如果是登陆客户
# 连接redis
# 获取set的值
# 获取card_%对于的值
# 循环遍历获取sku_id
# 3 如果非登陆客户
# 获取cooke中cart的值card_dict
'''
3.2 代码实现
   # 1  获取get请求先判断是否为登陆客户
try:
user=request.user
except:
user=None
# 2 如果是登陆客户
if user is not None and user.is_authenticated:
# 连接redis
# 获取card_%对于的
redis_con=get_redis_connection(CARD_CACHE_ALIAS)
# 获取set的值
cart_seleted=redis_con.smembers('cart_selected_%s'%user.id)
# 循环遍历获取sku_id
cart_redis=redis_con.hgetall('cart_%s'%user.id)
print(cart_redis)
print(type(cart_redis))
cart_data={}
for sku_id,count in cart_redis.items(): count=int(count.decode())
cart_data[sku_id.decode()]= {
'count':count,
'selected':sku_id in cart_seleted
}
# 3 如果非登陆客户
# 获取cooke中cart的值card_dict
else:
cart_data=get_cookie_key(request,'cart')
print(cart_data)
print(type(cart_data))
cart_list=[]
for sku_id in cart_data:
print(sku_id)
try:
sku=SKU.objects.get(id=sku_id)
except :
continue
cart_list.append({
'id': sku_id,
'name':sku.name,
'price':sku.price,
'count': cart_data[sku_id]['count'],
'selected':cart_data[sku_id]['selected']
})
return JsonResponse({'code':200,'data':cart_list})

4 购物车修改

4.1购物车修改的思路
     # 1 获取请求参数
# 2 判断用户是否登陆
# 3 登陆,重置redis数量,(商品数量,默认选中)
# 4 未登陆 ,获取cookie card_data,修改数量
4.2 代码实现
   def put(self,request):
# 1 获取请求参数
body_data = json.loads(request.body.decode())
sku_id = body_data.get('sku_id')
selected = body_data.get('selected')
count = body_data.get('count')
if sku_id is None:
return JsonResponse({'code': 401, 'errmsg': '参数不全'})
try:
sku = SKU.objects.get(id=sku_id)
except SKU.DoesNotExist:
return JsonResponse({'code': 401, 'errmsg': '商品错误'})
# 2 判断用户是否登陆
try:
user = request.user
except:
user = None
# 3 登陆,redis数量,(删除sku_id 相关 记录,如果选中,取消选中)
if user is not None and user.is_authenticated:
redis_con = get_redis_connection(CARD_CACHE_ALIAS)
redis_con.hset('card_%s'%user.id,sku_id,count)
if selected:
redis_con.sdd('card_selected_%s'%user.id,sku_id)
else:
redis_con.srem('card_selected_%s'%user.id,sku_id) return JsonResponse({'code':200}) # 4 未登陆 ,获取cookie card_data,修改数量
else:
card_dict=get_cookie_key(request,'card')
origin_count=card_dict[sku_id]['count']
count+=origin_count
card_dict[sku_id]={
'count':count,
'selected':selected
}
response=up_cookie_key('card',card_dict) return response

5 购物车删除

5.1购物车删除的思路
             # 1 获取请求参数
# 2 判断用户是否登陆
# 3 登陆,redis数量,(删除sku_id 相关 记录,如果选中,取消选中)
# 4 未登陆 ,获取cookie card_data,删除相关记录
5.2 代码实现
 def delete(self,request):

       # 1 获取请求参数
body_data=json.loads(request.body.decode())
sku_id=body_data.get('sku_id') if sku_id is None:
return JsonResponse({'code': 401, 'errmsg': '参数不全'})
try:
sku = SKU.objects.get(id=sku_id)
except SKU.DoesNotExist:
return JsonResponse({'code': 401, 'errmsg': '商品错误'})
# 2 判断用户是否登陆
try :
user=request.user
except :
user=None
# 3 登陆,redis数量,(删除sku_id 相关 记录,如果选中,取消选中)
if user is not None and user.is_authenticated: redis_con=get_redis_connection(CARD_CACHE_ALIAS)
redis_con.hdel('cart_%s'%user.id,sku_id)
redis_con.srem('cart_select_%s'%user.id,sku_id)
return JsonResponse({'code':200})
else:
# 4 未登陆 ,获取cookie card_data,删除相关记录
cart_dict=get_cookie_key(request,'cart')
if sku_id in cart_dict:
del cart_dict[sku_id]
response=up_cookie_key('cart',cart_dict)
return response

6 购物车的合并问题

合并问题就是,cookie和redis的购物车商品记录的取舍问题,本思路采用,以cooike为准,如果,有则覆盖,没有则增加;

6.1 功能实现思路
合并cookie 购物车到redis方案有多种,本次采用用cookie为主,
cookie 数据 { reids 数据 {
'1': { hash '1': count ‘4’:count
'count': 1,
'selected':1} set { sku}
合并的的业务逻辑:
# 1 从cookie 读取cart的数据;返回是一个字典 cookie_dict,但是redis存储的二进制元素,需要进行单独decode
sku_list=[sku_id.decode() for sku_id in redis_data] 把字典的key 生成一个列表生成式
# 2 遍历cookie_dict
# 2.1打开 redis_con 直接向跟sku_id 向redis hash 进增加数据,有则修改,以cooike为主,没有则增加
# redis.con.hset('cart_%s'%user.id,sku_id, cookie[sku_id]['count'])
# 2.2判断 cookie[sku_id]['selected']为真,则 进行 redis_con.sadd('cart_selected_%s'%user.id,sku_id),
# 否则,判断 skui_id 是否在集合中,存在,则删除
# 3 删除cookie, 设置和删除cookie必须使用response
# response.delete_cookie('cart') ;退出的时候cart换成用户名即可
'''
6.2 功能实现代码

​ 在系统登陆后直接调用该函数即可

from django.http import JsonResponse
from movice_fuli.settings import CARD_CACHE_ALIAS
def merege_cookie_redis(request,response):
# 1 从cookie 读取cart的数据;返回是一个字典 cookie_dict
card_dict = get_cookie_key(request, 'cart')
redis_con = get_redis_connection(CARD_CACHE_ALIAS)
user=request.user
redis_data=redis_con.hgetall('cart_%s'%user.id)
sku_list=[sku_id.decode() for sku_id in redis_data]
rp=redis_con.pipeline()
# 2 遍历cookie_dict
for sku_id in card_dict:
if sku_id in sku_list:
rp.hset('cart_%s'%user.id,sku_id,card_dict[sku_id]['count'])
if card_dict[sku_id]['selected']:
rp.sadd('cart_selected_%s'%user.id,sku_id)
else:
rp.srem('cart_selected_%s'%user.id,sku_id)
else:
rp.hset('cart_%s' % user.id, sku_id, card_dict[sku_id]['count'])
rp.execute()
# 3删除cookie信息
response.delete_cookie('cart')
return response

django购物车的实现的更多相关文章

  1. Django 购物车模板

    url from django.contrib import admin from django.urls import path, re_path from django.urls import i ...

  2. $Django 路飞之显示视频,Redis存购物车数据,优惠卷生成表,优惠卷的一个领取表。(知识小回顾)

    知识小回顾之json序列化问题 精髓:支持python的几种数据类型(注意不是对象,不能放对象),其次是tuple变list. ensure_ascii:默认值True,如果dict内含有non-AS ...

  3. django项目中购物车的实现

    对于做项目而言,最重要的是分析清楚自己负责模块的思路,确定思路后,把每一步实现的步骤确定后,根据步骤,去实现代码,测试. 购物车的逻辑:    登录用户可以添加购物车,未登陆用户页可以添加到购物车   ...

  4. Django实战(13):在session中保存购物车

    现在,我们有了一个产品目录界面,用户如果看到满意的产品,就可以将其放入购物车.下面就让我们来实现购物车的功能. 首先要做一下简单的分析和设计.购物车应该显示一系列产品的清单,其中列出了买方选中的产品. ...

  5. django 商城项目之购物车以及python中的一些redis命令

    最近在用django restframe框架做一个商城项目,有一个关于购物车的业务逻辑,是用cookie和redis存储的购物车信息,在这里记录一下. 完成一个商城项目,如果不做一个购物车,就是十分可 ...

  6. Django电商项目---完成购物车页面day4

    创建购物车项目App python manage.py startapp df_cart 初始化项目: manas/urls.py manas/settings.py 创建新文件:df_cart/ur ...

  7. Django 实现购物车功能

    购物车思路:使用 session 功能识别不同浏览器用户,使得用户不管是否登录了网站,均能够把想要购买的产品放在某个地方,之后随时可以显示或修改要购买的产品,等确定了之后再下订单,购物车可以用来暂存商 ...

  8. django中的构造字典(二级菜单,评论树,购物车)

    1.构造父子结构: 1.1需求样式 客户列表 customer_list /customer/list/ -----> 添加客户 customer_add /customer/add/ ---- ...

  9. Django day 37 网站视频的播放,购物车接口,优惠券表分析

    一:网站视频的播放, 二:购物车接口, 三:优惠券表分析

  10. python代码实现购物车(django的redis与vue)

    安装模块 pip install django-redis 后端代码 # 购物车 class CartView(APIView): # 初始化函数 def __init__(self): self.c ...

随机推荐

  1. Any to Any 实时变声的实现与落地丨RTC Dev Meetup

    前言 「语音处理」是实时互动领域中非常重要的一个场景,在「RTC Dev Meetup丨语音处理在实时互动领域的技术实践和应用」活动中,来自声网.微软和数美的技术专家,围绕该话题进行了相关分享. 本文 ...

  2. 小知识:SQL Monitor Report的使用

    在上一篇 优化利器In-Memory开启和效果 中,提到的两个SQL对比,使用的是传统的dbms_xplan.display_cursor方式来查看执行计划,好处是文本输出的通用性强,基本信息也都有. ...

  3. Centos 7配置使用nginx反向代理mysql

    背景:由于WEB服务和MySQL数据库服务分开部署的,由于网络问题限制,有时需要通过中间代理服务器跳转连接MySQL,所以需要在中间服务器上配置代理. 1.添加stearm模块 # nginx通常代理 ...

  4. Quicker 快速开发,控制脚本关闭(示例,鼠标连点器)

    前言 一般写Quicker脚本的时候,是不需要考虑中途手动退出脚本的,因为多数脚本的运行时间不长,没多少中途退出的需求.但一旦脚本需要后台不定时间运行(可能要连续运行很长时间),如果不能手动控制脚本终 ...

  5. React的组件化/工程化开发(脚手架)

    脚手架: create-react-app 安装脚手架: $ npm i create-react-app -g 检查安装: $ npm create-react-app --version 新建项目 ...

  6. 在已有的vue项目中添加单元测试模块

    package.json 添加新命令 "test": "jest",下载包: "jest": "^26.6.3", &q ...

  7. SwitchHosts operation not permitted 解决方案--亲测有效

    SwitchHost!是帮助我们管理Hosts的工具,可以帮助我们做域名解析, 弥补了如果要修改域名还要改计算机C:\Windows\System32\drivers\etc位置下的hosts文件的弊 ...

  8. odoo 开发入门教程系列-准备一些操作(Action)?

    准备一些操作(Action)? 到目前为止,我们主要通过声明字段和视图来构建模块.在任何真实的业务场景中,我们都希望将一些业务逻辑链接到操作按钮.在我们的房地产示例中,我们希望能够: 取消或将房产设置 ...

  9. 安装Minikube并启动一个Kubernetes环境

    安装Minikube并启动一个Kubernetes环境 Minikube 是一种轻量级的Kubernetes 实现,可在本地计算机上创建VM 并部署仅包含一个节点的简单集群.Minikube 可用于L ...

  10. 在 Kubernetes 集群上部署 VSCode

    在 Kubernetes 集群上部署 VSCode Visual Studio Code Visual Studio Code 是一个轻量级但功能强大的源代码编辑器,可在您的桌面上运行,适用于 Win ...