商城思路总结

美多商城

业务模式:B2C (个人到企业)

开发环境 ubuntu16.04+django1.11.11+mysql8+python3.5

项目模块:

  • 1,用户
    • 包括:注册(图形验证码,短信验证码)、登录(多条件登录,第三方登录,忘记密码)、用户中心(基本信息,邮箱激活,收获地址,个人订单,修改密码)
  • 2,商品
    • 包括:首页(首页广告,商品列表,商品搜索),列表页(热销排行),详情页(商品浏览记录)
  • 3,购物车
    • 包括:购物车管理,购物车合并,首页展示简单购物
  • 4,商品订单
    • 包括:确认订单,提交订单,订单商品评价
  • 5,用户支付
    • 支付宝支付
  • 6,程序上线
    • 页面静态化,数据库主从分离,消息队列优化,Nginx,uwsgi
  • 7,后台管理(MIS系统)
    • 数据统计,用户管理,权限管理,商品管理,订单管理

开发模式:

前后端不分离:为了提高搜索排名 SEO
页面整体刷新:django+jinja2
页面局部刷新:vue

项目流程架构:

用户请求--》Nginx代理服务器---》静态资源(css,js,首页,详情页)
			   ---》动态资源(uwsgi服务器转发)--》框架--》内部流程
				内部功能:数据存储MySQL 缓存Redis  异步任务Celery  消息队列RabbitMQ
					  文件存储FastDFS  全文检索ES 部署NGinx+uwsgi  定时任务Crontab
				调用接口:云短信,支付宝SDK,Oauth2.0认证 QQ互联

Django默认用户认证系统

处理用户账号、组、权限和基于cookie的用户会话
位置 django.contrib.auth
同时处理认证和授权
包含内容:用户,权限,组,密码

Django默认用户模型类

User对象是认证系统的核心 继承AbstractUser
自定义用户模型
	原因:要新增用户字段(手机号)
	迁移自定义用户模型类要配置 AUTH_USER_MODEL = 'users.User'

注册

  • 用户注册后端逻辑:

    • 接收参数–校验参数是否齐全–检验参数格式是否符合要求–检验短信验证码–保存用户数据–响应结果,重定向到首页
  • 用户状态保持:

    • 调用默认的login() 方法,把通过认证的用户唯一信息如user.id写入到session会话中
    • 前后端分离情况下:后端存储session,前端在cookie中存储session_id,实现用户登录后的身份认证
  • 用户名、手机号重复注册:

    • 用户输入信息–离开输入框触发js事件–ajax局部刷新–后台查询对应的数据是否存在–返回数据给前端–前端根据信息显示对应内容
  • 图形验证码:

    • 调用模块Captcha生成验证码
    • 前端页面刷新生成uuid–将uuid传给后端–调用模块生成验证码–将内容存到redis(过期时间5分)–将图片返回给前端显示
    • 注意:在这里图形验证码的目的是为短信验证码服务,防止机器疯狂发送短信
  • 短信验证码:

    • 发送调用第三方云短信
    • 点击发送短信(手机号,图形验证码)–接收参数–校验参数–提取图形码,删除图形码,对比图形码–生成,保存短信验证码–发送短信验证码
    • 避免频发短信:在后端缓存中存储对应标记,保存验证码同时保存发送标记,再点击就校验,通过返回json信息给前端提示
  • 前后端分离下跨域问题:

    • 根据浏览器同源策略:域=协议+域名+端口,在两个域中,以上三者中任意一个条件不同,均涉及到跨域的问题
    • 浏览器策略:浏览器先发一个options请求,检查当前的域名是否支持跨域,如果支持才会发送对应请求
    • 处理:CORS 使用django-cors-headers扩展
    • 流程:在后端注册应用’corsheaders’,配置中间件,添加白名单CORS_ORIGIN_WHITELIST,前端查询是否支持跨域,后端查询白名单中有没有对应信息
  • 异步任务:

    • 采用第三方短信发送验证码,会因为网络阻塞程序向下执行,影响用户体验
    • 采用Celery进行任务发送(分布式异步任务队列调度框架)
    • 优点:简单(即插即用),高效(每分钟数百万任务),错误自动重启(retry)
    • 1,支持定时任务和异步任务两种方式
    • 2,组成:client客户端发送任务–broker中间件–worker执行者–backend任务执行结果
    • 3,可以开启多线程也可以是多进程
    • 4,应用:解耦,耗时,队列
  • redis操作优化:

    • redis是B/S架构,客户端发送请求,监听socket返回,在服务端响应前是阻塞的
    • 同时处理多个请求,应采用管道pipeline发送(收集多个指令一次性发送一次性将结果返回)降低延时
    • 原理:队列,redis是单进程的服务,可以将多个命令放在一个tcp报文中发送,服务端将结果放在一个报文中返回,由于队列是先进先出,保证了顺序性

登录

登录逻辑:

输入参数提交--接收参数--校验参数(必传,格式)--认证登录用户--状态保持(设置时间一般2周)--返回响应
认证用户:使用django自带的authenticate()进行认证
状态保持:使用django自带的login() #其实内部实现了session记录
保持时间:session.set_expiry(0)设置session时间 0是关闭就过期, None是默认2周
登录的核心是:认证和状态保持

多账号登录:

实现用户名/手机号/邮箱登录
需要重写认证后端,即重写authenticate()方法
定义方法,当用户输入信息,判断是用户名还是手机号
然后重写认证方法,根据信息获取用户,再检查用户的密码user.check_password(password)
认证核心是:使用用户的唯一信息去查询数据库中是否有该用户

首页用户名展示:

登录成功后将用户名写入cookie,设定保持时间 set_cookie('username', user.username, max_age=3600 * 24 * 15)
在页面js从cookie中获取用户名,展示在前端页面上 this.username = getCookie('username')

退出登录:

调用自带的logout()  # 实际上内部调用了cookie的刷新方法,删除当前会话
清除cookie中信息 delete_cookie('username')

判断用户是否登录:

使用django认证系统的LoginRequiredMixin类来判断,只需要在类中继承即可
也可以使用request.user.is_authenticated()来判断用户是否登录
继承后需要配置重定向页面,默认是重定向 '/' LOGIN_URL = '/login/',重定向到登录页
用户认证系统还提供了一个next参数,用于记录用户未登录时页面信息,可以在登录成功后跳转回登录前页面
next 可以配合 login_required装饰器使用,都是判断是否登录
next = request.GET.get('next')

前后端分离情况下的登录:

前后端分离情况下,用户登录后状态保持不能依赖于cookie,自然session也不适用(session基于cookie)
session一般保持在服务器,客户端保存session_id,一般在cookie中,当服务器保存大量的session会对服务器造成压力
所以选择 token,token保存在客户端
认证机制:用户携带用户名和密码后端验证--服务器验证成功后生成token--token返回前端记录用户信息--再次请求,携带token,服务器解析验证,确定用户状态
可以使用JWT,构成分为头,载荷,签证,JWT-token生成需要密钥,密钥一般保存在服务器
在正常情况下,用户token有效期不会设置过长,为了保存用户状态,需要两个token,token和刷新token
token一般2个小时,刷新token一般2周,用户浏览中如果token失效,刷新token会自动请求一个新的token保持状态

单点登录SSO:

服务器中有多个子系统(如淘宝对应的还用天猫,超市,生鲜等)
用户在不同的系统中,服务器需要认证用户保持状态
一般采用的方法是重定向,即用户在主系统的登录成功后,如果在子系统登录,首先重定向到主的登录页面查看登录状态,如果登录,将对应的信息返回进行保持,
一般大型系统会有一个登录认证模块专门处理

QQ登录:

登录流程:
用户点击第三方qq登录
网站跳转到qq登录页面
用户输入用户名,密码或者扫码向qq发起登录请求(qq的扫码登录页面)
qq服务器认证成功后将用户引导到回调网址中,并返回qq服务器的code值(code拼接重定向网址)
用户重定向到美多页面并携带了qq服务器的code
后端接收到code后向qq服务器请求access token
qq服务器返回access token
后端再通过access token向qq服务器获取用户的唯一标识open_id
qq服务器返回open_id,后端通过open_id查询当前用户是否绑定用户
如果绑定过用户,记录存在,就实现状态保持,跳转到首页
如果没有绑定用户,跳转到绑定页面,在这里进行用户绑定,
用户存在(即手机号注册过)直接绑定,用户不存在就直接书册用户进行绑定

要定义对应的模型,是用户和open_id的对应信息
使用的第三方包是 QQLoginTool
在用户进行绑定用户时,需要将open_id携带到绑定页面,为了数据安全,需要使用数据加密
这是使用第三方包itsdangerous,可以生成加密后的数据,还可以设置有效期 
初始化加密工具  使用密钥 Serializer(settings.SECRET_KEY, expires_in=3600)

忘记密码:

用户发送请求,携带用户名和验证码
后端验证图片验证码,通过账号查询用户,返回用户的手机号给前端,并生成发送短信的token(载荷mobile),发送验证码
用户填写验证码并携带token到后端(token是为了标记用户 验证码是谁发的,校验又是校验谁的)
后端接收到收集验证码(校验),通过手机号获取对应用户,生成修改密码的token(载荷user对象),重定向到修改密码页面
前端填写完新密码后,携带token到后端重置密码(有用户,旧密码,新密码)

用户中心:

用户基本信息:

用户信息是登录用户才能访问,使用LoginRequiredMixin验证登录用户
前端页面加载完成后向后端发送请求
后端验证后判断用户登录,获取用户user模型
将用户信息返回前端,进行展示

添加验证邮箱:

添加邮箱:
接收参数(在请求体中添加的数据通过request.body获取)--校验参数--给用户添加邮箱

用户响应json数据(默认的验证登录MIxin类不返回json数据)--重写MIxin类,定义为JsonMixin类
发送邮件:
需要配置发送的邮箱服务器(邮箱回调--授权密码)
使用异步任务发送邮件--对邮件中验证用户信息使用itsdangerous进行加密(用户id,用户email)
验证邮箱:用户点击邮箱链接--指定页面--后端获取加密后token信息--验证token--获取用户--修改用户激活邮箱字段--返回结果

收货地址:

页面刷新--点击获取地址数据--判断是否有省份数据--如果没有就查询省份数据--有就查询市区数据--通过父级数据获取子级数据parent_model.subs.all()
序列化数据返回
数据需要缓存--运用django自身的缓存工具cache,设置缓存时间为1小时--具体查询时先查询缓存再查询数据库

新增地址逻辑:
填写提交--判断用户现有地址数量(地址总数有限制)--接收参数--校验参数--保存地址信息--返回json数据,页面局部刷新
删除地址:
查询要删除地址--将地址逻辑删除设为True--保存信息--返回响应刷新

修改密码:

接收参数--验证参数(格式--2次密码是否一致)--验证原密码是否正确--更新密码(request.user.set_password(new_password))--重定向--删除cookie--重新登录

商品:

商品分析:

SPU:标准产品单位  SKU:库存量单位
广告表分为:广告类别,广告内容
商品表分为:商品频道组,商品频道,商品类别,商品(SPU),商品(SKU),商品品牌,spu规格,sku规格,sku图片,商品规格选项

首页广告:

展示频道分类:
查询商品频道--获取首级频道--通过首级查子级--通过子级查孙级(for cat2 in cat1.subs.all())--构建序列化数据输出

商品列表页:

面包屑导航:
利用三级分类--获取当前分类--判断是否存在父级(if category.parent is None)--判断是否存在子级(category.subs.count())

分页和排序:
接收排序关键字参数--按照关键字进行排序查询--order_by(sort_field)
分页利用django分页器--Paginator:查询商品数据--创建分页器--获取每页商品数据--获取列表总页数--序列化数据返回响应

热销排行:
热销商品在一定时间内是不变的--可以利用缓存进行缓存--减少服务器压力
查询按信息,按销量排序,取前三序列化返回前端页面展示

商品详情页:

路由调用需要获取具体的产品id,/detail/(?P<sku_id>\d+)/
后端接收路由传递的参数--查询对应信息--查询频道分类和面包屑导航--返回渲染结果
通过商品查询对应的规格信息(参数--评价--详情等) sku.spu.specs.order_by('id')

统计商品访问量:建立对应模型(商品分类--数量)
商品点开--获取商品id--获取当前日期--查询该商品今天访问量,有就+1没有就新建一个访问记录

用户浏览记录:临时数据,数据量不大,经常变化--选择存储在内存中,因为记录和顺序有关,且是一个id对应多个信息所以选择list
每个用户浏览记录最多存储5个商品sku信息
存储逻辑:先去重--再存储--最后截取
用户点击详情页--接收参数(商品id)--查询商品--执行存储lpush[user_id:sku_id]

商品搜索:

要求:输入商品关键字,返回相应的搜索结果
方案一:使用模糊查询like,缺点:效率低,多个字段使用不方便,[SQL使用like 配合% _, ORM使用 字段__contains=关键字 查询]
方案二:使用Elasticsearch全文检索
搜索引擎原理:先对数据库数据进行一遍预处理,建立一份索引数据结构--索引记录了关键字和词条的对应关系,并记录词条位置

Elacticsearch是java实现的开源搜索引擎,底层是lucene,python没法直接使用需要使用接口调用(haystack),默认不支持中文分词(IK, jieba)
使用流程:
安装haystack--注册应用和路由--配置引擎和索引库,自动更新索引--建立索引类(索引类文件,模板文件,生成索引)--配置搜索结果页面(search.html)
调用:请求参数q,调用API路径/search/,主路由文件直接关联haystack搜索--结果返回--可以配置页面显示条数(结合页面分页)--HAYSTACK_SEARCH_RESULTS_PER_PAGE = 5

购物车:

用户购物车数据存储时需要做唯一性标识
存储选择:登录用户存储在redis中(因为用户,商品,数量,勾选状态很难统一存储,所以选择不同类型 用户:商品,数量 hash  用户:勾选商品 set)
hash适合存储对象,比如一个人的个人信息,需要修改较多的数据等,商品对应的数量有很大可能变化,而set适合存储单一数据与列表不同是,列表存储是顺序的
未登录用户存在cokie中,存在cookie中需要对数据进行序列化 pickle.dumps() 将数据转成二进制,base64.b64encode()将二进制数据进行编码(8位转6位)
由于设计的格式不同,在需要合并购物车操作时,需要将数据合适转成一致的格式
也可以设计成:{sku id :[count,True]} True表示选中

订单:

结算后台逻辑:

获取用户--查询地址信息--从购物车中查询勾选的商品信息--计算金额和数量--补充运费--返回页面渲染

提交订单:

订单表格:订单基本信息,订单商品
提交订单流程:
后台获取地址和支付方式--校验信息--获取用户--生成订单编号--遍历购物车信息,增加销量减少库存,清除购物车中数据--保存订单信息--返回响应
事务:要么成功,要么失败,可以通过django.db.transaction模块提供的atomic定义事务
并发下数据出错问题使用乐观锁下单,保证数据的完整性
展示下单成功页面(订单id,支付方式,支付金额)在30分钟内要完成支付(如果没有完成那么就要回滚状态,恢复库存,减少销量)

支付:

对接支付宝SDK:

安装SDK--申请沙箱账号--配置RSA2公私钥
电脑网站支付流程:
用户下单支付--调用支付SDK向支付接口发起请求--返回登录界面--用户登录支付宝--选中支付方式,输入支付密码
--获取回调页面URL--支付成功以异步通知为准,查询支付结果,返回支付结果页面--返回回调页面,显示支付的具体结果,交易信息(支付订单号,交易流水号)
--后台收到回调结果后,检查信息--确认信息是支付宝发出的--保存支付结果--修改订单状态--显示订单详细信息

(文件存储方案)FastDFS:

是一款开源的轻量级分布式文件系统
功能包括:文件存储、文件访问(上传,下载)、文件同步,解决了大容量存储和负载均衡问题,适合以文件为载体的网站服务
架构:client、tracker(跟踪、调度、负载均衡)、storage(存储服务器)
storage群横向可以备份,纵向可以备份
文件存储后返回客户端一个文件索引(组名/虚拟磁盘路径/数据两级目录/文件名)

(容器方案)Docker:

保持相同的运行环境,避免相同重复的工作,缩短代码从开发、测试到部署、上线运行的周期(程序可一致易于协作)
docker可以创建虚拟化的沙箱环境可以供测试使用
Docker是一个C/S架构程序,轻量级应用容器框架
三个概念:镜像(只读的文件系统,可以创建容器),容器(镜像运行实例,实质是镜像层上加一个可操作的容器层),仓库(类似github,托管镜像)
安装(17.03)--检查安装结果--启动服务--从仓库拉取镜像(本地镜像安装)--开启容器服务--查看映射路径

页面静态化:

首页静态化:

目的:减少查询次数、提升页面响应效率
页面静态化:将动态渲染生成的页面保存成html文件,放到静态文件服务器中(Nginx)
注意点:动态数据不能静态化(热销、新品、分页排序),用户数据不能静态化(用户名,购物车数据),对于不能静态化数据可以先获得页面再异步请求获取数据
定义生成静态文件方法--执行获取首页数据--渲染页面--将页面写入文件的任务
启动静态服务器

定时任务:可以使用django-crontab扩展
安装--注册--设定定时任务(分时日月周)--配置定时任务--将定时任务添加到系统中

详情页静态化:

目的:减少用户数据库查询提升页面响应效率
注意:与首页不同的是,1,数据变化不频繁,2,有具体数据不能静态化
定义生成静态文件脚本--获取当前商品信息--获取商品规格信息--执行定时任务生成静态文件

MySQL读写分离:

优点:多台服务器提高读写性能,主从备份提升数据安全
主从同步:基于二进制日志,主服务器使用二进制日志记录数据库变化情况,从服务器读取和执行该日志文件保持数据一致
主从应保存SQL版本一致
从docker仓库获取mysql镜像--指定,修改丛机配置文件--运行,测试是否成功--配置主机,备份数据--从机收集数据执行备份--
django配置读写分离--配置中添加读写不同的数据库配置--创建读写的路由文件--配置指定读写路由文件

RabbitMQ:

消息队列:可靠性高,可以持久化消息,吞吐量大
安装镜像--运行创建容器--在celery连接配置(broker_url= 'amqp://guest:guest@127.0.0.1:5672')--这就是celery配合的原因,使用方便

部署:

Nginx服务器作为静态文件服务器
配置目录--收集静态文件--修改服务器配置--启动服务器--测试访问

利用Nginx反向代理动态业务
实际生产采用uwsgi服务器运行django程序
调整配置文件--配置生产环境启动文件--安装uwsgi--新建uwsgi配置文件--启动uwsgi服务器--部署nginx反向代理--启动nginx
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值