开源web框架django知识总结(十九)
阿尔法商城(购物车)
购物车存储方案
新建apps->carts
- 必须是用户登录状态下,才可以保存购物车数据。
- 用户对购物车数据的操作包括:增、删、改、查、全选等等
- 每个用户的购物车数据都要做唯一性的标识。
1. 购物车存储方案
1.存储数据说明
- 如何描述一条完整的购物车记录?
- 用户,选择了两个 iPhone8 添加到了购物车中,状态为勾选
- 一条完整的购物车记录包括:
用户
、商品
、数量
、勾选状态
。 - 存储数据:user_id、sku_id、count、selected
2.存储位置说明
- 购物车数据量小,结构简单,更新频繁,所以我们选择内存型数据库Redis进行存储。
- 存储位置:dev.py文件中Redis数据库 5号库
"carts": {
# 购物车
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://192.168.42.128:6379/5",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
3.存储类型说明
- 提示:我们很难将用户、商品、数量、勾选状态存放到一条Redis记录中。所以我们要把购物车数据合理的分开存储。
- 用户、商品、数量:
hash
carts_user_id: {sku_id1: count, sku_id3: count, sku_id5: count, ...}
- 勾选状态:
set
- 只将已勾选商品的sku_id存储到set中,比如,1号和3号商品是被勾选的。
selected_user_id: [sku_id1, sku_id3, ...]
注释:Redis Smembers 命令返回集合中的所有的成员。 不存在的集合 key 被视为空集合。
4.存储逻辑说明
- 当要添加到购物车的商品已存在时,对商品数量进行累加计算。
- 当要添加到购物车的商品不存在时,向hash中新增field和value即可。
==============================================
购物车管理
添加购物车
提示:在商品详情页添加购物车使用局部刷新的效果。
1. 添加购物车接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | post |
请求地址 | /carts/ |
2.请求参数:JSON
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
sku_id | int | 是 | 商品SKU编号 |
count | int | 是 | 商品数量 |
selected | bool | 否 | 是否勾选 |
3.响应结果:JSON
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
2. 添加购物车后端逻辑实现
1.接收和校验参数 carts.views.py
import json
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from django_redis import get_redis_connection
from utils.views import login_required # 注意修改导包路径
from goods.models import SKU
# Create your views here.
class CartsView(View):
# 把sku商品加入购物车
@method_decorator(login_required)
def post(self, request):
# 1、提取参数
data = json.loads(request.body.decode())
sku_id = data.get('sku_id')
count = data.get('count')
selected = data.get('selected', True)
# 2、校验参数
if not all([sku_id, count]):
return JsonResponse({
'code': 400, 'errmsg': '缺少参数!'})
if not isinstance(selected, bool):
return JsonResponse({
'code': 400, 'errmsg': '参数有误!'})
# 3、判断是否登陆
user = request.user
if user.is_authenticated:
# 4、登陆写入redis
conn = get_redis_connection('carts')
# 4.1 记录sku商品数量——carts_<user_id> : {sku_id: count}
# conn.hmset('carts_%s'%user.id, {sku_id:count}) # 我们不能使用该函数,因为他会覆盖原有数据
conn.hincrby('carts_%s'%user.id, sku_id, amount=count) # 把sku商品数量增加count,如果不存在则新建
# 4.2 记录选中状态——selected_<user_id> : [sku_id]
if selected:
conn.sadd('selected_%s'%user.id, sku_id)
return JsonResponse({
'code': 0, 'errmsg': 'ok'})
=========================================
展示购物车
1. 展示购物车接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /carts/ |
**2.请求参数:**无
3.响应结果:HTML cart.html
4.后端接口定义 carts.views.py
class CartsView(View):
def get(self, request):
# 0、初始化一个空字典,用于保存sku购物车数据,其格式和cookie购物车格式一样
cart_dict = {
} # {1: {count:xx, selected:xx}}
user = request.user
if user.is_authenticated:
# 1、用户登陆,则从redis中读取sku商品信息
pass
2. 展示购物车后端逻辑实现
1.查询Redis购物车
2.查询购物车SKU信息
3.返回响应数据
# 展示购物车
@method_decorator(login_required)
def get(self, request):
# 0、初始化一个空字典,用于保存sku购物车数据,其格式和cookie购物车格式一样
cart_dict = {
} # {1: {count:xx, selected:xx}}
user = request.user
if user.is_authenticated:
# 1、用户登陆,则从redis中读取sku商品信息
conn = get_redis_connection('carts')
# 2、sku商品数量、是否选中
# cart_redis_dict = {b'1': b'8'}
cart_redis_dict = conn.hgetall('carts_%s' % user.id)
# cart_redis_selected = [b'1']
cart_redis_selected = conn.smembers('selected_%s' % user.id) #smembers返回集合中的所有的成员。 不存在的集合 key 被视为空集合
#将cart_redis_dict与cart_redis_selected合并
for k, v in cart_redis_dict.items(): #字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。
# k: b'1'; v: b'8'
cart_dict[int(k)] = {
'count': int(v),
'selected': k in cart_redis_selected # b'1' in [b'1']返回True
}
cart_skus = []
# 3、构建响应返回
for k, v in cart_dict.items():
# k: sku_id; v: {count:xx, selected: xx}
sku = SKU.objects.get(pk=k)
cart_skus.append({
'id': sku.id,
'name': sku.name,
'count': v['count'],
'selected': v['selected'],
'price': sku.price,
'default_image_url': sku.default_image_url.url,
'amount': sku.price * v['count']
})
return JsonResponse({
'code': 0, 'errmsg': 'ok', 'cart_skus': cart_skus})
==============================================
修改购物车
提示:在购物车页面修改购物车使用局部刷新的效果。
1. 修改购物车接口设计和定义
1.请求方式
选项 | 方案 |
---|---|
请求方法 | PUT |
请求地址 | /carts/ |
2.请求参数:JSON
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
sku_id | int | 是 | 商品SKU编号 |
count | int | 是 | 商品数量 |
selected | bool | 否 | 是否勾选 |