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. graphviz 简单入门

    上一位负责画图的选手 CS Academy 由于不明原因暂时不能继续工作,所以本俱乐部招收了新选手 graphviz. 在 Linux 上,你可以这么下载: sudo apt install grap ...

  2. Spring IOC——源码分析

    Spring 容器的 refresh() 创建容器 1 //下面每一个方法都会单独提出来进行分析 2 @Override 3 public void refresh() throws BeansExc ...

  3. OpenAI Kubernetes 相关博文读后笔记

    一.概述 最近 ChatGPT 和其公司 OpenAI 特别火:ChatGPT 3, ChatGPT 3.5, New Bing, ChatGPT 4... 怀着学习的心态,这几天访问了 OpenAI ...

  4. 全网最详细中英文ChatGPT-GPT-4示例文档-信息智能提取从0到1快速入门——官网推荐的48种最佳应用场景(附python/node.js/curl命令源代码,小白也能学)

    目录 Introduce 简介 setting 设置 Prompt 提示 Sample response 回复样本 API request 接口请求 python接口请求示例 node.js接口请求示 ...

  5. R语言数据加工厂——plyr包使用

    plyr包是Hadley Wickham大神为解决split – apply – combine问题而写的一个包,其动机在与提供超越for循环和内置的apply函数族的一个一揽子解决方案.使用plyr ...

  6. CentOS8安装Oracle datebase 19C

        我这里安装Oracle数据库是rpm格式的包.需要先得有以下依赖包关系,先依次按此顺序安装. yum install ./compat-libcap1-1.10-7.el7.x86_64.rp ...

  7. StampedLock:JDK1.8中新增,比ReadWriteLock还快的锁

    摘要:StampedLock是一种在读取共享变量的过程中,允许后面的一个线程获取写锁对共享变量进行写操作,使用乐观读避免数据不一致的问题,并且在读多写少的高并发环境下,比ReadWriteLock更快 ...

  8. 四月二十二日java基础知识

    1.利用接口实现类的多重继承:java语言中接口的主要作用是可以帮助实现类似于类的多重继承功能.多重继承,是指一个子类可以有一个以上的直接父类,该子类可以直接继承它所有父类的非私有成员.2.一个类实现 ...

  9. SpringBoot2:@Configuration 注解

    @Configuration 这个注解的作用,告诉 springboot 这是一个配置类.配置类以及类里的方法都可以作为Bean.里面的方法用@Bean标记. @Configuration 替换了繁琐 ...

  10. IIS 部署.NET CORE 项目 出现 HTTP 错误 500.19 - Internal Server Error

    当出现这个错误时是因为服务器上没有.NET CORE对应的SDK以及运行时文件,我的.NET CORE版本是2.2,下载的就是2.2对应的文件. 附上.NET CORE2.2版本的下载链接 下载 .N ...