美多商城项目(八)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
全局流量管理 GTM,标准版 1个月
简介: 美多商城项目(八)


项目仓库

  1. https://github.com/EthanYan6/E-commerce-sites.git

结合代码查看笔记,效果更佳。笔记只是记录重点或者难点。


每日分享

It is our attitude at the beginning of a difficult task which, more than anything else, will affect its successful outcome.

我们在开始做一件富有挑战性的任务时,对于成功的影响,没有什么比我们的态度更为关键的了。

小闫语录

在大一的时候,英语老师曾经送给我们一句话『Attitude is everything.』态度决定一切。其实一件事成功与否,在这份工作上是否有建树,从一开始就决定了,那便是我们对其的态度。客观的困难不足以阻挡前进的脚步,畏惧的态度才是失败的根本原因,其他的事情就算是直接原因,那也只是『压死骆驼身上的最后一根稻草』。有着必胜的决心,不畏难的坚定,端正的态度,前方路上的困难都将是小的磕磕绊绊,你的成功从开始的这一刻便已注定,加油!



美多商城项目(八)

1.项目每次启动前开启的任务

1.前端服务器live-server开启(在静态文件目录下执行)

live-server

2.开启celery任务(在celery_task上一级目录终端进行输入)

celery -A celery_task.main worker -l info

3.开启定时任务

# 添加定时任务到系统中
python manage.py crontab add
# 显示已经激活的定时任务
python manage.py crontab show
# 移除定时任务
python manage.py crontab remove

4.开启tracker服务器

docker container start tracker

5.开启storage服务器

docker container start storage

6.开启elasticsearch服务器

docker container start elasticsearch

7.进入redis查看

# 进入redis
redis-cli
# 选择数据库
select <数据库序号>

8.进入mysql数据库

mysql -h<主机地址> -P<端口号> -u<用户名> -p<密码>

2.购物车记录添加

API: POST /cart/
参数:
    通过请求头传递jwt token
    {
        "sku_id":"添加商品id",
        "count":"数量",
        "selected":"勾选状态", # 可以不传,默认是勾选状态
    }
响应:
    {
        "sku_id":"添加商品id",
        "count":"数量",
        "selected":"勾选状态"
    }

2.1业务逻辑

1.获取参数并进行校验(参数完整,sku_id商品是否存在,商品库存是否足够[可有可无,添加购物车可要可不要,下单时必须有])。

2.获取校验之后的数据。

3.获取user。

4.保存用户的购物车记录。

4.1如果用户已经登录,在redis中保存用户的购物车记录。

4.1.1获取redis链接。

hash:在redis hash中存储用户购物车添加的商品id和数量count。

如果购物车已经添加过该商品,数量需要进行累加,如果未添加,直接添加一个新元素。

hincrby
1. hincrby <key> <field> <increment>

给redis hash中指定field属性的值累加increment,如果field属性不存在,直接添加一个新的属性和值。

1. set: 在redis set中存储用户购物车勾选的商品id
2.     
集合中的元素是唯一的
sadd
1. sadd <key> <member> ...

向redis set中添加元素,集合中元素是唯一的。

查看redis中是否存在。

# hash中查看所有的域field和他的值value
hgetall xxx
# set中获取key域集合的所有元素
smembers <key>

4.2如果用户未登录,在cookie中保存用户的购物车记录。

4.2.1获取原始cookie的购物车数据。

4.2.2解析cookie中购物车数据。

cart_dict = pickle.loads(base64.b64decode(cookie_cart))

4.2.3如果购物车已经添加过该商品,数量需要进行累加。

通过看商品的id是不是在购物车数据字典中,可以得知是否添加过。

4.2.3如果购物车没有添加过该商品,直接添加一个新元素。

5.返回应答,购物车记录添加成功。

5.1设置cookie中购物车数据

cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

如过出现认证未通过,可以重写父类APIView中的perform_authentication方法,直接pass跳过认证。我们在获取用户的时候使用request.user也会触发认证机制,我们可以手动对错误进行捕获而不让其报错停止。如果进行访问的时候没有传递jwt用户,是不会进行jwt验证的,会将其作为匿名用户处理。

3.购物车记录获取

API: GET /cart/
参数:
    通过请求头传递jwt token
响应:
    [
        {
            "id":"商品id",
            "name":"商品名称",
            "price":"商品价格",
            "default_image_url":"默认图片",
            "count":"数量",
            "selected":"勾选状态"
        },
        ...
    ]

3.1业务逻辑

1.获取用户的购物车记录

1.1如果用户已登录,从redis中获取用户的购物车记录。

1.1.1获取redis链接

redis_conn = get_redis_connection('cart')

1.1.2从redis hash中获取用户购物车中添加的商品id和对应的数量count

hgetall
1. hgetall <key>

获取redis hash中所有的属性和值

1.1.3从redis set中获取用户购物车中勾选的商品id

smembers
1. smembers <key>

获取redis set中所有的元素

1.2如果用户未登录,从cookie中获取用户的购物车记录。

1.2.1获取cookie中购物车的数据。如果没有数据是None。

1.2.2解析cookie中购物车数据

cart_dict = pickle.loads(base64.b64decode(cookie_cart))

2.根据用户购物车中商品id获取对应商品的数据。

2.1给sku对象增加属性count和selected,分别保存该商品在购物车中添加数据和勾选状态。

3.将购物车商品数据序列化并返回。

3.1添加购物车商品序列化器类。

3.2将数据序列化并返回。

4.购物车记录修改

API: PUT /cart/
参数:
    通过请求头传递jwt token
    {
        "sku_id":"商品id",
        "count":"修改数量",
        "selected":"修改勾选状态"
    }
响应:
    {
        "sku_id":"商品id",
        "count":"修改数量",
        "selected":"修改勾选状态"
    }

4.1业务逻辑

1.获取参数并进行校验(参数完整性,sku_id商品是否存在,商品的库存)。

1.1获取校验之后的数据。

1.2获取user。

调用request.user会触发DRF框架认证过程。

2.修改用户的购物车记录。

2.1如果用户已经登录,修改redis中对应的购物车记录。

2.1.1获取redis链接。

2.1.2修改redis hash中商品id对应数量count。

hset

  1. hset <key><field><value>

将redis hash中指定的field属性值设置为value。

2.1.3修改redis set中勾选的商品id。

2.1.3.1勾选,那么添加新元素。

sadd

  1. sadd <key><member>...

向redis set中添加元素,集合中元素是唯一的。

2.1.3.2取消勾选,将其移除。

srem移除

  1. srem <key><members>...

从redis set中移除指定的元素,有则移除,无则忽略。

2.1如果用户没有登录,修改cookie中对应的购物车记录。

2.1.1获取cookie中的购物车数据。

2.1.2如果购物车没有数据。

2.1.3如果购物车中有数据,解析cookie中的购物车数据。

  1. cart_dict = pickle.loads(base64.b64decode(cookie_cart))

如果获取的字典为空,表示购物车无数据。

2.1.4修改购物车数据。

3.返回应答,购物车记录修改成功。

3.1设置cookie中购物车数据。

  1. cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

3.2返回应答,购物车记录修改成功。


总结

1.购物车记录增加

hincrby sadd

2.购物车记录获取

hgetall smembers

3.购物车记录修改

hset sadd srem

对于上面的三个接口,都需要考虑用户是登录还是未登录。

让视图跳过DRF框架认证过程。


5.购物车记录删除

API: DELETE /cart/
参数:
    通过请求头传递jwt token
    {
        "sku_id":"商品id"
    }
响应:
    {
        "sku_id":"商品id"
    }

5.1业务逻辑

1.获取商品skuid并进行校验(skuid必传,sku_id对应商品是否存在)。

1.1获取校验之后的数据。

1.2获取用户,防止触发DRF框架的认证机制,对错误进行捕获。

2.删除用户的购物车记录。

2.1如果用户已登录,删除redis中对应的购物车记录。

2.1.1获取redis链接

2.1.2从redis hash中删除对应商品的id和数量count

hdel

  1. hdel <key><field>...

删除redis hash中指定的field属性和值。

2.1.3从redis set中删除对应商品的id

srem移除

  1. srem <key><members>...

从redis set中移除指定的元素,有则移除,无则忽略。

2.2如果用户未登录,删除cookie中对应的购物车记录。

2.2.1获取cookie中的购物车记录。

2.2.2如果无数据,直接返回204;如果有数据需要解析cookie中购物车数据。

  1. cart_dict = pickle.loads(base64.b64decode(cookie_cart))

2.2.3删除对应的购物车记录。

2.2.4重新设置cookie购物车数据。

  1. cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

3.返回应答,购物车记录删除成功。

6.全选和取消全选

API: PUT /cart/selection/
参数:
    通过请求头传递jwt token
    {
        "selected": "勾选状态", # True:全选, False:取消全选 
    }
响应:
    {
        "message": "OK"
    }

6.1业务逻辑

1.获取参数selected并进行校验(selected必传)。

1.1获取校验之后的selected。

1.2获取用户。

2.设置用户购物车记录勾选状态。

2.1如果用户已登录,设置redis中用户购物车记录勾选状态。

2.1.1获取redis链接。

2.1.2从redis hash中获取用户购物车中所有商品的id。

2.1.3全选:将用户购物车所有商品的id添加到redis set中。

2.1.4全不选:将用户购物车所有商品的id从redis set中移除。

2.2如果用户未登录,设置cookie中用户购物车记录勾选状态。

2.2.1获取cookie的购物车记录。

2.2.2解析cookie中的购物车数据

  1. cart_dict = pickle.loads(base64.b64decode(cookie_cart))

2.2.3设置cookie购物车记录勾选状态。

3.返回应答,设置成功。

3.1设置cookie中的购物车数据

  1. cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

7.购物车记录合并

7.1需求

用户登录时,将cookie中的购物车数据合并到登录用户redis购物车记录中。

7.2实现

只需将购物车记录合并封装成函数,然后在登录过程进行调用。

登录过程调用合并购物车函数

1.普通账户密码登录。

2.QQ登录。

7.2.1购物车记录合并方案

# 假如id为2的用户登录之前
# cookie中的购物车记录如下
{
    11:{
        'count': 1,
        'selected': False
    },
    15: {
        'count': 2,
        'selected': True
    }
}
cart_dict = {
    11: 1,
    15: 2
}
cart_selected_add = [15]
cart_selecte_remove = [11]
# redis中的购物车记录如下
cart_2: {
    '11': '2',
    '16': '3',
    '9': '1'
}
cart_selected_2:('11', '9')

如果id为2的用户进行了登录,需要将cookie中的购物车数据合并到用户redis购物车记录中,如何进行合并?

答:当进行购物车记录合并时,如果cookie中的购物车数据和redis中的购物车数据发生了冲突,直接以cookie中的购物车数据为准,用cookie中的购物车数据去覆盖redis中对应的数据。如果没有冲突,都进行保留。

cart_2: {
    '11': '1',
    '15': '2',
    '16': '3',
    '9': '1'
}
cart_selected_2('15','9')

11的数据因为发生了冲突,覆盖后,取消了勾选。

7.2.2举例

假如id为2的用户登录之前,cookie中的购物车记录如下:

1. {
2.     1: {
3.         'count': 3,
4.         'selected': False
5.     },
6.     3: {
7.         'count': 2,
8.         'selected': True
9.     },
10.     5: {
11.         'count': 2,
12.         'selected': True
13.     }
14. }
redis中的购物车记录如下:
1. cart_2: {
2.     '1': '2',
3.     '5': '1',
4.     '7': '3'
5. }
6. cart_selected_2: ('1', '7')
合并之后的数据如下:
1. cart_2: {
2.     '1': '3',
3.     '3': '2',
4.     '5': '2',
5.     '7': '3'
6. }
7. cart_selected_2: ('3', '5', '7')

7.3封装合并购物车记录函数

7.3.1目的

将cookie中的购物车记录合并到登录用户的redis记录中。

7.3.2业务逻辑

1.获取cookie中购物车记录。

2.如果cookie购物车中无数据,就不需要合并了。

3.如果cookie购物车中有数据,需要解析cookie中的购物车数据。

  1. cart_dict = pickle.loads(base64.b64decode(cookie_cart))

4.如果解析出来的字典为空,表明cookie购物车中无数据,也不需要合并。

5.将cookie中购物车记录合并到登录用户的redis记录中

6.组织一个字典,存储cookie购物车记录中添加的商品id和对应数量count。此字典中的数据在进行购物车记录合并时需要设置到redis hash中。

7.组织一个列表,存储cookie购物车记录中被勾选的商品的id。此列表中的商品的id在进行购物车记录合并时,需要添加到redis set中。

8.组织一个列表,存储cookie购物车记录中未被勾选商品的id。此列表中商品id在进行购物车记录合并时需要从redis set中移除。

9.遍历解析之后的字典,将勾选与未勾选的数据分别加入对应的列表中。

10.合并:将组织的字典中key和value作为属性和值设置到redis对应的hash元素中。

11.将需要添加到redis的列表中商品id添加到redis对应的set元素中。

12.将需要从redis中移除的列表中商品的id从redis对应的set元素中移除。

13.删除cookie中购物车数据。

1. response.delete_cookie('cart')
hmset
1. hmset <key> <field> <value> [<field> <value>....]

同时将多个field属性和值设置到哈希表key中。此命令会覆盖以存在的属性。

7.4修改登录视图

rest_framework_jwt提供的obtain_jwt_token视图,
实际从rest_framework_jwt.views.ObtainJSONWebToken类视图而来,
我们可以重写此类视图里的post方法来添加合并逻辑。

登录视图

 from rest_framework_jwt.views import ObtainJSONWebToken
 class UserAuthorizeView(ObtainJSONWebToken):
     """
     用户认证
     """
     def post(self, request, *args, **kwargs):
         # 调用父类的方法,获取drf jwt扩展默认的认证用户处理结果
         response = super().post(request, *args, **kwargs)
         # 仿照drf jwt扩展对于用户登录的认证方式,判断用户是否认证登录成功
         # 如果用户登录认证成功,则合并购物车
         serializer = self.get_serializer(data=request.data)
         if serializer.is_valid():
             user = serializer.validated_data.get('user')
           response = merge_cart_cookie_to_redis(request, user, response)
         return response
修改路径users/urls.py
. urlpatterns = [
.     ...
.     # url(r'^authorizations/$', obtain_jwt_token),
.     url(r'^authorizations/$', views.UserAuthorizeView.as_view()),
.     ...
. ]

QQ登录

修改oauth/serializers.py中的序列化器

class OAuthQQUserSerializer(serializers.ModelSerializer):
    ...
    def create(self, validated_data):
        ...
        # 向视图对象中补充user对象属性,以便在视图中使用user
        self.context['view'].user = user
        return user

修改oauth/views.py中的视图

class OAuthQQUserView(CreateAPIView):
    """
    获取QQ用户对应的美多商城用户
    """
    serializer_class = OAuthQQUserSerializer
    def get(self, request):
        ...
        else:
            reponse = Response({
                'token': token,
                'username': user.username,
                'user_id': user.id
            })
            # 合并购物车
            response = merge_cart_cookie_to_redis(request, user, response)
            return response
    def post(self, request, *args, **kwargs):
        response = super().post(request, *args, **kwargs)
        # 合并购物车
        response = merge_cart_cookie_to_redis(request, self.user, response)
        return response
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue的大学生二手电子产品交易平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的大学生二手电子产品交易平台的详细设计和实现(源码+lw+部署文档+讲解等)
83 0
|
7月前
|
小程序 关系型数据库 MySQL
Gitee项目分享——学之思开源考试系统,食堂大妈看完都学会了
Gitee项目分享——学之思开源考试系统,食堂大妈看完都学会了
|
7月前
|
开发框架 小程序 Java
免费开题报告|基于SpringBoot+Vue的校内跑腿平台
免费开题报告|基于SpringBoot+Vue的校内跑腿平台
100 0
免费开题报告|基于SpringBoot+Vue的校内跑腿平台
|
Linux 数据库 文件存储
美多商城项目(六)
美多商城项目(六)
|
存储 安全 数据安全/隐私保护
美多商城项目(二)
美多商城项目(二)
|
应用服务中间件 API 数据库
美多商城项目(十)
美多商城项目(十)
|
存储 搜索推荐 NoSQL
美多商城项目(七)
美多商城项目(七)
|
SQL NoSQL 关系型数据库
美多商城项目(九)
美多商城项目(九)
|
存储 Shell 数据库
美多商城项目(四)
美多商城项目(四)
|
API 数据库 数据安全/隐私保护
美多商城项目(三)
美多商城项目(三)