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

美多商城项目(七)

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

正文共: 7620字 4图 预计阅读时间: 20分钟

每日分享

If you can change your mind, you can change your life.

如果你愿意改变你的想法,你可以改变你的人生。

小闫语录

有时候失败并不是你不够努力,而是你对自己的盲目自信,以及那份固执。坚持该坚持的,改变该改变的,放弃该放弃的,前面将是柳暗花明。有些人明知道自己是错的,但是那可怜的自尊心让其不愿承认其他人的正确,那份小傲娇会让你付出巨大的代价。还有些人是因为缺少从头再来的勇气,宁愿一错再错,其实从头再来并没有那么难,难的是做出这个决定。

美多商城项目(七)

项目仓库

代码语言:javascript
复制
https://github.com/EthanYan6/E-commerce-sites.git

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

1.登录用户浏览商品记录

Django开发web项目中,如果是前后端分离的模式,那么基本都是使用rest_framework框架。如果是前后端不分离,就不会使用了。tornado学习难度会大一点。

1.什么时候需要获取登录用户浏览商品的记录? 何时取?

答:当登录用户进入个人信息页面时,需要获取登录用户浏览商品的记录。

2.什么时候需要保存登录用户浏览商品的记录? 何时存?

答:当登录用户浏览某个商品的详情页面时,需要保存登录用户浏览商品的记录。

3.浏览记录保存在哪里? 存在哪?

答:如果将浏览记录保存在MySQL数据库的表中,用户频繁的浏览商品,就需要频繁的操作MySQL数据库,相应性能有所下降。

id

user_id

sku_id

1

2

3

表格中的信息代表id为2的用户浏览了id为3的商品

将用户浏览记录存储在redis中

4.在redis中怎么存储登录用户浏览记录? 怎么存?

答:采用列表的数据类型存储。

代码语言:javascript
复制
list: history_<user_id>: [<sku_id>,...]

redis存储分为五种数据类型。以key-value形式存储。

代码语言:javascript
复制
# 1.string: 字符串
    history_<user_id>: '3,5,1'
    #上述方法存储后,取值时,可以按`,`进行分割。
    例如:
        user_2: '1,5'
        user_3: '3,5'

# 2.hash: 哈希    key: {field:value, field: value}
    history: {
        <user_id>:'3,5,1',
        <user_id>:'1,2',
        ...
    }

# 3.list: 列表    key: [value, ...]
    history_<user_id>: [3, 5, 1]

# 4.set: 无序集合 
    不能使用,因为用户浏览记录是有序的。

# 5.zset: 有序集合
    需要额外加权重值,然后按权重值进行排序。

字符串和hash存储的时候需要额外的字符串操作,而列表直接可以存储,然后直接取值。zset需要额外的权重值来保证有序,而列表不需要。

1.1浏览记录保存

代码语言:javascript
复制
API: POST /browse_histories/
参数:
    通过请求头传递jwt token
    {
        "sku_id": "商品id"
    }
响应:
    {
        "sku_id": "商品id"
    }

在redis中存储浏览记录的过程:

代码语言:javascript
复制
history_2: ['1','3','5']
# 如果id为2的用户又浏览了id为4的商品,将记录保存在列表左侧
history_2: ['4','1','3','5']
# 如果id为2的用户又浏览了id为3的商品,我们需要去重

在redis中存储浏览记录的过程:
# 去重:如果商品已经被浏览,需要将商品id先从列表中移除。
# 保持有序:最新浏览商品的id添加到list列表最左侧。
# 截取:只保留最新几个浏览商品id
lrem
代码语言:javascript
复制
lrem <key> <count> <value>

从redis列表中移除元素,有则删除,无则忽略,不会报错。

代码语言:javascript
复制
my_list:[1,3,2,3,5,3,6]
# 要删除所有的3
lrem my_list 0 3
# 从左往右将3删除2次
lrem my_list 2 3
# 从右往左将3删除2次
lrem my_list -2 3
lpush
代码语言:javascript
复制
lpush <key> <value> ...

向redis列表左侧加入元素。

ltrim
代码语言:javascript
复制
ltrim <key> <start> <stop>

保留redis列表指定区间内元素。

业务逻辑

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

定义序列化器类来实现校验。

2.在redis中存储登录用户浏览的记录。(create)

在序列化器类中定义create方法

代码语言:javascript
复制
a.获取redis链接对象 StrictRedis
b.拼接key
c.去重:如果商品已经被浏览,需要将商品id先从列表中移除。
d.保持有序:最新浏览的商品的id添加到list列表最左侧。
e.截取:只保留最新几个浏览商品id。

3.返回应答,浏览记录添加成功。

如果create中返回的是validated_data,那么接口中的serializer.data返回的就是一个对象。 如果create中返回的是一个字典,那么接口中的serializer.data返回的就是一个字典。

在redis中进行查看:

a.打开redis客户端

代码语言:javascript
复制
redis-cli

b.选择4号库

代码语言:javascript
复制
select 4

c.查看里面的所有记录

代码语言:javascript
复制
keys *

1.2浏览记录获取

代码语言:javascript
复制
API: GET /browse_historise/
参数:
    通过请求头传递jwt token
响应:
    [
        {
            "id": "商品id",
            "name": "商品名称",
            "price": "商品价格",
            "default_image_url": "默认图片",
            "comments": "评论量"
        },
        ...
    ]
lrange
代码语言:javascript
复制
lrange <key> <start> <stop>

返回一个列表,包含指定区间内的元素。超出范围的下标取值不会引起错误。

闭区间

目的:获取redis列表指定区间内的元素。

业务逻辑

1.获取redis链接对象 StrictRedis

2.拼接key

3.从redis中获取登录用户浏览的商品sku_id。

4.根据商品sku_id获取对应商品数据。

5.将商品的数据序列化并返回响应。

2.获取分类SKU商品的数据

根据第三级分类ID获取分类SKU商品的数据。

a.支持分页功能。

b.支持排序功能。

代码语言:javascript
复制
API: 
GET /categories/(?P<category_id>\d+)/skus/?page=<页码>&page_size=<页容量>&ordering=<排序字段>
参数:
    通过url传递第三极分类ID
响应:
    [
        "count": "总数量",
        "next": "下一页链接地址",
        "previous": "上一页链接地址",
        "results": [
            {
                "id": "商品id",
                "name": "商品名称",
                "price": "商品价格",
                "default_image_url": "默认图片",
                "comments": "评论量"
            },
            ...
        ]
    ]

业务逻辑

1.根据 category_id获取分类SKU商品的数据。

2.将商品的数据序列化并返回。

self.kwargs:是一个字典dict,保存的是从url地址中提取的所有命名参数。


总结

1.浏览记录

浏览记录存储:(何时存、何时取、存在哪、怎么存)

浏览记录添加:去重lrem、左侧加入lpush、截取ltrim

浏览记录获取:lrange

2.分类SKU商品数据

根据第三级分类id获取sku商品的数据

支持分页

支持排序


3.商品搜索

3.1需求

根据商品的名称和副标题搜索商品的数据。

举例

关键字:iPhone

sql语句:

代码语言:javascript
复制
select * from tb_sku where name like '%iPhone%' or caption like '%iPhone%';

在SQL语句查询中,like语句查询效率很低,在搜索的时候不会使用SQL,而是使用搜索引擎。

3.2搜索引擎

3.2.1.搜索引擎概念&原理

3.2.2.搜索引擎功能

3.2.3.搜索引擎环境搭建

3.2.4.Django对接搜索引擎

3.2.1概念

可以对数据表中的数据进行处理,建立索引结构数据( 记录索引记录和数据库中真实数据之间对应关系),在搜索引擎建立索引结构数据时,还会对 索引字段进行关键词拆分,然后保存每个关键字在哪些索引记录中存在。

索引字段:根据哪些表字段来搜索数据,这些字段就是索引字段。

id

name

caption

...

...

1

Apple iPhone 8 Plus (A1864) 256GB 深空灰色 移动联通电信4G手机

选【移动优惠购】新机配新卡,198优质靓号,流量不限量!

2

Apple iPhone 8 Plus (A1864) 256GB 金色 移动联通电信4G手机

选【移动优惠购】新机配新卡,198优质靓号,流量不限量!

AppleiPhone8Plus(A1864)256GB深空灰色移动联通电信4G手机\n选【移动优惠购】新机配新卡,198优质靓号,流量不限量!

搜索引擎作用:针对索引字段的内容进行关键词的分词并建立对应的索引数据。

slor/whoosh/es/....搜索引擎有很多,我们选择es(Elasticsearch)。es是开源的,目前全文搜索引擎的首选。是Java实现的。

3.2.2搜索引擎功能

1.建立索引结构的数据。

2.根据关键字检索对应的索引的记录。

注意:拿到索引记录之后,对应数据库中真实的数据,需要自己进行查询,搜索引擎不会去做。

3.3.3环境搭建

获取镜像,可以通过网络pull

代码语言:javascript
复制
docker image pull delron/elasticsearch-ik:2.4.6-1.0

或者加载其他人提供的镜像文件

代码语言:javascript
复制
docker load -i elasticsearch-ik-2.4.6_docker.tar

修改elasticsearch的配置文件 elasticsearc-2.4.6/config/elasticsearch.yml第54行,更改ip地址为本机ip地址

代码语言:javascript
复制
network.host: 10.211.55.5

创建docker容器运行,注意将elasticsearc-2.4.6目录放置到home目录

代码语言:javascript
复制
docker run -dti --network=host --name=elasticsearch -v /home/python/elasticsearch-2.4.6/config:/usr/share/elasticsearch/config delron/elasticsearch-ik:2.4.6-1.0

检查是否启动成功:

浏览器放问下面的地址,如果返回了内容,那么搜索引擎启动成功。

代码语言:javascript
复制
<自己电脑IP>:9200

es默认端口是9200

3.3.4Django对应es搜索引擎

作为开发者,如果自己写代码对接搜索引擎,需要了解很多搜索引擎内部原理操作。

全文检索框架:帮助开发者使用搜索引擎的功能。

Python中使用haystack框架,它支持多种搜索引擎,帮助开发者使用搜索引擎的功能。

全文检索框架功能

1.帮助开发者利用搜索引擎建立索引结构数据。

2.帮助开发者利用搜索引擎根据关键字来检索索引记录。

3.帮助开发者根据索引记录到数据库中查询真实的数据。

通过使用haystack来调用Elasticsearch搜索引擎

1.安装:

代码语言:javascript
复制
pip install drf-haystack
pip install elasticsearch==2.4.1

drf-haystack是为了在REST framework中使用haystack而进行的封装(如果在Django中使用haystack,则安装django-haystack即可)

2.注册应用

代码语言:javascript
复制
INSTALLED_APPS = [
    ...
    'haystack',
    ...
]

3.配置:在配置文件中配置haystack使用的搜索引擎后端

代码语言:javascript
复制
# Haystack全文检索框架配置
HAYSTACK_CONNECTIONS = {
    'default': {
        # 指定所使用的搜索引擎
        'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
        # 指定es搜索引擎服务器地址
        'URL': 'http://192.168.59.225:9200//',  # 此处为elasticsearch运行的服务器ip地址,端口号固定为9200
        # 指定elasticsearch建立的索引库的名称
        'INDEX_NAME': 'meiduo',  # 指定elasticsearch建立的索引库的名称
    },
}

# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

HAYSTACKSIGNALPROCESSOR 的配置保证了在Django运行起来后,有新的数据产生时,haystack仍然可以让Elasticsearch实时生成新数据的索引

haystack对接es搜索引擎

1.建立索引结构数据。

1.1建立索引类

在子应用下新建文件search_indexes.py

文件名是固定的

在template下面建立目录search,在search目录下建立目录indexes,在indexes目录下建立目录<子应用名>,在这个目录下建立文件,文件名如下:

代码语言:javascript
复制
文件名格式:<模型类名小写>_text.txt

所有的名称都是固定不变的。

1.2指定索引字段

1.3执行命令,建立索引数据:

代码语言:javascript
复制
python manage.py rebulid_inex

2.编写搜索API接口。

代码语言:javascript
复制
API: GET /skus/search/?text=<搜索关键字>
参数:
    通过text查询字符串传递<搜索关键字>
响应:
    ...

代码:

代码语言:javascript
复制
# GET /skus/search/?text=<搜索关键字>
class SKUSearchViewSet(HaystackViewSet):
    # 指定索引类对应模型类
    index_models = [SKU]

    # 指定搜索结果序列化时所使用的序列化器类
    # 搜索结果中每个对象都包含两个属性:
    # text:索引字段的内容
    # object:从数据库中搜索出模型对象
    serializer_class = SKUIndexSerializer

4.购物车记录存储

需求:登录用户和未登录用户都能进行购物车记录添加。

4.1存储方案

4.1.1登录用户的购物车记录存储

1.存在哪?redis

答:存在redis中。因为如果存储在mysql中,用户频繁的操作购物车的记录(删除或这添加),就需要频繁操作mysql数据库。在redis中存储登录用户的购物车记录。读写效率要快很多。

如果采用MySQL数据库,需要设计如下表格:

id

user_id

sku_id

count

select(勾选状态)

1

2

1

3

1

2.怎么存?

答:每个登录用户的购物车记录采用redis中两条数据来存:

hash:存储登录用户购物车中添加的商品id和对应数量。

set:存储登录用户购物车中被勾选的商品id。

代码语言:javascript
复制
# hash: 哈希 <key>: {<field>: <value>, ...}
cart_<user_id>: {
    <sku_id>: <count>,
    <sku_id>: <count>,
    ...
}

# set:集合
cart_selected_<user_id>: ('<sku_id>','<sku_id>', ...)

例如:
    cart_2: {
        '1':'3',
        '3':'2',
        '5':'1'
    }
    id为2用户购物车记录:
        id为1的商品添加了3件;
        id为3的商品添加了2件;
        id为5的商品添加了1件;
    cart_selected_2: ('1','5')
        id为1和5的商品对应的购物车记录是被勾选的。
4.1.2未登录用户购物车记录存储

1.存在哪?客户端cookie中

答:未登录用户可能根本不是网站注册用户,只访问一次就永不访问,如果将购物车记录存储到服务器,可能会造成服务器存储空间浪费,所以可以直接未将登录用户购物车记录存储到客户端。

cookie/sessionSrotage/LocalStorage三种存储方式,我们选择存储到cookie中。

2.怎么存?

答:

代码语言:javascript
复制
'cart': {
    <sku_id>: {
        'count': '<count>',
        'selected': '<selected>'
    },
    <sku_id>: {
        'count': '<count>',
        'selected': '<selected>'
    },
    ...
}

例如:
'cart': {
    1: {
        'count':2,
        'selected': False
    },
    5: {
        'count':1,
        'selected': True
    },
    3: {
        'count': 5,
        'selected': False
    }
}
未登录用户购物车包含id为1,3和5的商品。
id为1的商品添加了2件;
id为5的商品添加了1件;
id为3的商品添加了5件;
id为5的商品是被选中的。

3.Django中cookie设置和获取

答:

代码语言:javascript
复制
# 1.设置cookie
response.set_cookie('<key>','<value>',max_age='<有效时间:s>')

# 2.获取cookie
request.COOKIES.get('<key>')

# json模块
json.dumps(dict):将字典转换为json字符串
json.loads(json字符串):将json字符串转化为字典

# pickle模块-python标准模块
pickle.dumps(dict|对象):将传入的数据转换为bytes字节流
pickle.loads(bytes字节流):将bytes字节流转换为dict|对象

# base64模块
base64.b64encode(bytes字节流):将传入的bytes字节流进行base64编码,返回编码之后的bytes内容。
base64.b64decode(编码之后的bytes字节流|str):将传入的内容进行base64解码,返回解码之后的内容。

# 设置cookie中购物车数据:
cart_data = bae64.b64encode(pickle.dumps(cart_dict)).decode()
response.set_cookie('cart',cart_data,max_age='过期时间:s')

# cookie中购物车数据解析
cookie_cart = request.COOKIES.get('cart')
cart_dict = pickle.loads(base64.b64decode(cookie_cart.encode()))
或者cart_dict = pickle.loads(base64.b64decode(cookie_cart))

优质文章推荐:

公众号使用指南

redis操作命令总结

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

Flask框架重点知识总结回顾

项目重点知识点详解

难点理解&面试题问答

flask框架中的一些常见问题

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

重点内容回顾-DRF

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 每日分享
  • 美多商城项目(七)
    • 项目仓库
      • 1.登录用户浏览商品记录
        • 1.1浏览记录保存
        • 1.2浏览记录获取
      • 2.获取分类SKU商品的数据
        • 业务逻辑
      • 总结
        • 1.浏览记录
        • 2.分类SKU商品数据
      • 3.商品搜索
        • 3.1需求
        • 3.2搜索引擎
      • 4.购物车记录存储
        • 4.1存储方案
    相关产品与服务
    云数据库 Redis
    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档