前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >美多商城项目(八)

美多商城项目(八)

作者头像
小闫同学啊
发布2019-07-18 12:59:43
1K0
发布2019-07-18 12:59:43
举报
文章被收录于专栏:小闫笔记小闫笔记

正文共: 8098字 5图 预计阅读时间: 21分钟

项目仓库

代码语言:javascript
复制
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开启(在静态文件目录下执行)

代码语言:javascript
复制
live-server

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

代码语言:javascript
复制
celery -A celery_task.main worker -l info

3.开启定时任务

代码语言:javascript
复制
# 添加定时任务到系统中
python manage.py crontab add
# 显示已经激活的定时任务
python manage.py crontab show
# 移除定时任务
python manage.py crontab remove

4.开启tracker服务器

代码语言:javascript
复制
docker container start tracker

5.开启storage服务器

代码语言:javascript
复制
docker container start storage

6.开启elasticsearch服务器

代码语言:javascript
复制
docker container start elasticsearch

7.进入redis查看

代码语言:javascript
复制
# 进入redis
redis-cli
# 选择数据库
select <数据库序号>

8.进入mysql数据库

代码语言:javascript
复制
mysql -h<主机地址> -P<端口号> -u<用户名> -p<密码>

2.购物车记录添加

代码语言:javascript
复制
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链接。

代码语言:javascript
复制
hash:在redis hash中存储用户购物车添加的商品id和数量count。

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

hincrby

代码语言:javascript
复制
hincrby <key> <field> <increment>

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

代码语言:javascript
复制
set: 在redis set中存储用户购物车勾选的商品id
    集合中的元素是唯一的

sadd

代码语言:javascript
复制
sadd <key> <member> ...

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

查看redis中是否存在。

代码语言:javascript
复制
# hash中查看所有的域field和他的值value
hgetall xxx
# set中获取key域集合的所有元素
smembers <key>

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

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

4.2.2解析cookie中购物车数据。

代码语言:javascript
复制
cart_dict = pickle.loads(base64.b64decode(cookie_cart))

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

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

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

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

5.1设置cookie中购物车数据

代码语言:javascript
复制
cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

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

3.购物车记录获取

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

3.1业务逻辑

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

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

1.1.1获取redis链接

代码语言:javascript
复制
redis_conn = get_redis_connection('cart')

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

hgetall

代码语言:javascript
复制
hgetall <key>

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

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

smembers

代码语言:javascript
复制
smembers <key>

获取redis set中所有的元素

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

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

1.2.2解析cookie中购物车数据

代码语言:javascript
复制
cart_dict = pickle.loads(base64.b64decode(cookie_cart))

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

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

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

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

3.2将数据序列化并返回。

4.购物车记录修改

代码语言:javascript
复制
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

代码语言:javascript
复制
hset <key> <field> <value>

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

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

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

sadd

代码语言:javascript
复制
sadd <key> <member> ...

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

2.1.3.2取消勾选,将其移除。

srem移除

代码语言:javascript
复制
srem <key> <members> ...

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

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

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

2.1.2如果购物车没有数据。

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

代码语言:javascript
复制
cart_dict = pickle.loads(base64.b64decode(cookie_cart))

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

2.1.4修改购物车数据。

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

3.1设置cookie中购物车数据。

代码语言:javascript
复制
cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

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


总结

1.购物车记录增加

hincrby sadd

2.购物车记录获取

hgetall smembers

3.购物车记录修改

hset sadd srem

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

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


5.购物车记录删除

代码语言:javascript
复制
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

代码语言:javascript
复制
hdel <key> <field> ...

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

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

srem移除

代码语言:javascript
复制
srem <key> <members> ...

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

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

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

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

代码语言:javascript
复制
cart_dict = pickle.loads(base64.b64decode(cookie_cart))

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

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

代码语言:javascript
复制
cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

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

6.全选和取消全选

代码语言:javascript
复制
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中的购物车数据

代码语言:javascript
复制
cart_dict = pickle.loads(base64.b64decode(cookie_cart))

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

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

3.1设置cookie中的购物车数据

代码语言:javascript
复制
cart_data = base64.b64encode(pickle.dumps(cart_dict)).decode()

7.购物车记录合并

7.1需求

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

7.2实现

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

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

1.普通账户密码登录。

2.QQ登录。

7.2.1购物车记录合并方案
代码语言:javascript
复制
# 假如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中对应的数据。如果没有冲突,都进行保留。

代码语言:javascript
复制
cart_2: {
    '11': '1',
    '15': '2',
    '16': '3',
    '9': '1'
}
cart_selected_2('15','9')

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

7.2.2举例

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

代码语言:javascript
复制
{
    1: {
        'count': 3,
        'selected': False
    },
    3: {
        'count': 2,
        'selected': True
    },
    5: {
        'count': 2,
        'selected': True
    }
}

redis中的购物车记录如下:

代码语言:javascript
复制
cart_2: {
    '1': '2',
    '5': '1',
    '7': '3'
}
cart_selected_2: ('1', '7')

合并之后的数据如下:

代码语言:javascript
复制
cart_2: {
    '1': '3',
    '3': '2',
    '5': '2',
    '7': '3'
}
cart_selected_2: ('3', '5', '7')

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

7.3.1目的

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

7.3.2业务逻辑

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

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

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

代码语言:javascript
复制
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中购物车数据。

代码语言:javascript
复制
response.delete_cookie('cart')

hmset

代码语言:javascript
复制
hmset <key> <field> <value> [<field> <value>....]

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

7.4修改登录视图

代码语言:javascript
复制
rest_framework_jwt提供的obtain_jwt_token视图,
实际从rest_framework_jwt.views.ObtainJSONWebToken类视图而来,
我们可以重写此类视图里的post方法来添加合并逻辑。
登录视图
代码语言:javascript
复制
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

代码语言:javascript
复制
urlpatterns = [
    ...
    # url(r'^authorizations/$', obtain_jwt_token),
    url(r'^authorizations/$', views.UserAuthorizeView.as_view()),
    ...
]
QQ登录

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

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

        return user

修改oauth/views.py中的视图

代码语言:javascript
复制
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操作命令总结

前端中那些让你头疼的英文单词

Flask框架重点知识总结回顾

项目重点知识点详解

难点理解&面试题问答

flask框架中的一些常见问题

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

重点内容回顾-DRF

Django相关知识点回顾

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈技术精选 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目仓库
  • 每日分享
  • 美多商城项目(八)
    • 1.项目每次启动前开启的任务
      • 2.购物车记录添加
        • 2.1业务逻辑
      • 3.购物车记录获取
        • 3.1业务逻辑
      • 4.购物车记录修改
        • 4.1业务逻辑
      • 总结
        • 5.购物车记录删除
          • 5.1业务逻辑
        • 6.全选和取消全选
          • 6.1业务逻辑
        • 7.购物车记录合并
          • 7.1需求
          • 7.2实现
          • 7.3封装合并购物车记录函数
          • 7.4修改登录视图
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档