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. Goravel ORM 新增模型关联,用 Golang 写关联也可以跟 Laravel 一样简单

    关于 Goravel Goravel 是一个功能完备.具有良好扩展能力的 Web 应用程序框架.作为一个起始脚手架帮助 Golang 开发者快速构建自己的应用.框架风格与 Laravel 保持一致,让 ...

  2. 博客与AI

    最近AI自动生成技术文章和答案在圈子里面引起了很大轰动,Stack Overflow暂时拒绝接收GPT生成的结果.我也经常性地浏览或者编写博客,但是最近我使用new bing或者ChatGPT的过程中 ...

  3. MyBatis 源码

    一.准备工作 MyBatis 工作流程:应用程序首先加载 mybatis-config.xml 配置文件,并根据配置文件的内容创建 SqlSessionFactory 对象:然后,通过 SqlSess ...

  4. AndroidBanner - ViewPager 03

    AndroidBanner - ViewPager 03 上一篇文章,描述了如何实现自动轮播的,以及手指触摸的时候停止轮播,抬起继续轮播,其实还遗留了一些问题: 当banner不可见的时候,也需要停止 ...

  5. Android Activity的事件分发机制-源码解析

    查看Activity的dispatchTouchEvent方法: public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getActio ...

  6. pandas小技巧

    1. 删除列 import pandas as pd df.drop("Unnamed: 0", axis=1, inplace=True) 2. 转换列的格式 df[" ...

  7. FreeSWITCH添加iLBC编码及转码

    操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 一.安装ilbc库 从第三方库里下载指定版本: git clone https://freeswitch.org/s ...

  8. lua变量、数据类型、if判断条件和数据结构table以及【lua 函数】

    一.lua变量[ 全局变量和局部变量和表中的域] Lua 变量有三种类型:全局变量和局部变量和表中的域. 全局变量:默认情况下,Lua中所有的变量都是全局变量. 局部变量:使用local 显式声明在函 ...

  9. 小程序TS报错 "无法重新声明块范围变量。此处也声明了xx "

    初学者简单的方法,目前还没有遇到问题 想法很简单,当export导出,骗eslint认为是一个模块. 如果有新的问题欢迎留言,我也在学习 1 import utilsApi from '../util ...

  10. NC51101 Lost Cows

    题目链接 题目 题目描述 \(N (2 \leq N \leq 8,000)\) cows have unique brands in the range 1..N. In a spectacular ...