部署
静态部署
使用Nginx提供静态文件,反向代理,业务服务器使用uwsgi+Django
Nginx 反向代理服务器
反向代理
负载均衡
请求转发
收集静态文件
配置文件中配置收集之后存放的目录
在项目目录下python manager.py collectstatic
打开Nginx的配置文件
配置端口80 , 域名, 路径指向静态文件
重启Nginx配置文件
动态文件部署
修改setting为生产环境的, DEBUG=Flase, Allow Host, CROS
在wsgi文件中指定setting
安装uwsgi
在wsgi同级目录下创建uwsgi.ini文件, 修改socket, 指定项目目录 + wsgi.py路径
在Nginx里面配置动态业务逻辑的端口8000, 域名,location
在/etx/host
指定访问的域名到Nginx的ip地址
问题
docker
cerely
fastdfs
mysql的索引原则和优化
isdanger的使用
xadmin
功能思路
底层csrf的实现
CORS , 安装依赖包, 应用, 中间件, 白名单, 实现前后端分离的跨域
加密方法:
对称加密和非对称加密
对称加密
使用pickle 和 base64
解密: cart = pickle.loads(base64.b64decode(cart.encode()))
加密: cookie_cart = base64.b64encode(pickle.dumps(cart)).decode()
使用isdangerous.TimedJSONWebSignatureSerializer
实例化对象 = TimedJSONWebSignatureSerializer(secret_key, 过期时间)
.dumps(data).decode()
.loads(token)
非对称加密RSA
两对钥匙(公钥和私钥)
openssl
OpenSSL> genrsa -out app_private_key.pem 2048 # 私钥RSA2
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
OpenSSL> exit
保存自己的私钥和对方的公钥
功能:
-------------注册分为三步, 第一步是图片验证码, 第二步是短信验证码, 第三步是注册
第一步前端传给UUID作为唯一标识,传给后端接口, 后端校验通过后, 调用封装模块生成图片验证码, 用UUID作为键值, 图片test作为value, 设置过期时间,在redis数据库存储为string类型,
返回给前端图片的image
第二步需要用户的手机号, UUID和 test参数, 后端 rest Framework使用序列化器验证图片验证码,验证通过后在视图函数里面生成6位随机数, 同样以mobile, 图片验证码保存在redis
调用三方的阿里云等服务,发送短信验证码信息,
第三步
传入参数用户名,手机号, 手机验证码, 密码一, 密码2, 是否同意协议等信息, 后端序列化器, 验证两次密码是否相同, 验证短信验证码, 创建用户保存到数据库, 实现状态保持
优化:
使用cerely发送短信验证码
mian.py 实例化应用app,加载配置文件, 自动注册cerely任务
不同的功能,封装到不同模块, tasts.py文件里面实现功能逻辑, 用实例化的应用app装饰器装饰逻辑函数
调用使用函数后面加delay(参数)调用
开启cerely使用serely -A 应用包路径 worker -l info
避免频繁发送请求短信验证码
使用pipline管道操作redis
用户名是否已经存在
前端传入用户名, 后端查询数据库用户名查到的count, 1代表已注册
状态保持用的是JWT
JWT是头部, 载荷, 签证,三部分, 头部保存, 头部保存加密算法,载荷可以有一些信息, 服务器拿着钥匙根据头部的信息对头部和载荷进行加密, 和签证比较
生成的token作为user的临时属性
--------------登录
使用的是jwt里面的obtain_jwt_token,
实现自定义的用户名和手机号都可以登录, 重写了方法authenticate(), 改变了user的判断方式实现
配置模块里声明
--------------第三发登录
根据第三发的开发文档,携带参数访问三方给的接口, 得到三方的登录地址
返回前端访问该地址
用户登录后, 在设置好的回调地址后面携带了再次请求的参数
拿到参数,访问三方,得到三方对于用户的唯一身份标识
根据标识符查询数据库,数据库没有数据, 用户不是第一次登录,登录成功
不是第一次登录, 回调到一个用户信息登录界面, 得到用户信息,后在绑定到用户信息
--------------邮箱验证
发送验证信息, 用户点击验证
发送验证信息
生成发送验证邮箱的url, 回调地址拼接 , 加密后的用户名和邮箱信息
使用isdangerous 里的TimedJSONWebSignatureSerializer 实例化对象的dumps方法加密
使用cerely异步发送给用户邮箱
前端传给我回调地址读取的用户名和邮箱信息, isdangerous解码验证通过后, 验证字段设为1
--------------页面静态化
首页频繁访问, 为了提升访问速度, 使用页面静态化
封装方法
构造数据
数据加载到模板里面
把模板放到制定位置
setting里面配置template存放目录, 和保存静态文件的目录
-------定时任务
安装定时任务依赖包django-crontab
setting
添加到应用里面
设置定时任务, 指定时间间隔, 执行方法, 日志存放位置
python manage.py crontab add
python manage.py crontab show, 展示已激活的定时任务
python manage.py crontab remove
-------使用脚本
普通的.sh文件
#!/bin/bash
py文件
#!/user/bin/env python
1 sys添加解释器路径
2加载django配置文件
if not os.getenv('django_settings_module'):
os.environ['django_settings_module'] = setting路径
3初始化django
import django
django.setup()
4 运行文件
---------------购物车
用户未登录数据存放在cookie里面, 已经登陆存放在redis里面, 登陆的时候
-------------增 skuid, sount, selected
重写父类的用户验证方法,不在进入视图前就检查JWT
post方法
把data = request.data传入序列化器,验证skuid是否存在, 库存量
验证通过后读取验证后的sku_id, count, selected
判断用户是否存在
存在保存在redis里面
不存在保存在客户端cookies里面
------------查
get方法 无参数
判断用户是否登陆
登陆从redis里面读取
未登陆从cookie里面读取
同意构造字典
在字典里面找到所有sku
传入序列化器序列化数据
返回序列化器.data
-------------改
put 方法 skuid, count, selected
数量和selectd直接覆盖
序列化器验证sku_id是否存在, 库存是否够
验证通过后从序列化器中读取数据
判断用户是否登陆
登陆修改redis里面的数据,
return Response(serilizer.data)
未登录修改cookies里面的数据
response = Response(serilizer.data)
response.set_cookie('cart', data, max_age=)
return response
-------------删
delete 方法 skuid
序列化器验证商品是否存在
验证通过后判断用户是否登陆
登陆删除reids里面的数据
未登录删除cookie里面的数据
-------------全选
put方法 传入参数selected是false或者true
序列化器验证传入参数是否是bool类型
验证通过后
判断用户是否已经登陆
登陆的从reids里面读取所有的skuid, 根据是否全选, 更改数据
未登录的从cookie里面读取数据把selected=selected
-------------登陆合并购物车
封装函数
读取所有的cookie里面的数据
读取所有redis里面的信息
构造字典存放skuid: count和勾选的集合
遍历cookie的字典加到redis里面
如果sku_id 重合则覆盖count
最后保存字典cart和勾选信息到redis
删除response.delete_cookie('cart')
return response
在登陆的地方调用
-------------购物车异常状态的处理
----------------订单
-------------生成订单
使用模型类序列化器, 和订单结算序列化器, 一个字段使用=模型类序列化器
校验用户已经登陆
get 方法处理
得到用户对象 ***
读取redis用户勾选的商品信息
把信息传入模型订单结算序列化器
return Response(serializer.data)
-------------保存订单
传入地址, 和支付方式 返回订单编号
序列化器序列化, 继承模型列序列化器, 改变地址和支付方式为只写, 必传
保存订单在def create(self, validated_data)
书写主要业务逻辑
1 获取用户
2生成订单编号
3保存订单基本信息
创建模型类对象
4从redis数据库里面获取购物车的信息
读取勾选商品, 构造字典
5遍历结算商品
遍历商品, 保存原始库存
判断库存是否充足
不充足raise serializer.ValidationError('')
充足的话减少库存
增加销量
使用乐观锁, 根据原始库存和sku_id查找,找到修改,往下走,没找到continue
增加订单的金额,和总购买数量
保存订单商品信息 break 退出循环下单
6redis里面删除已结算商品
return order
--------------三方支付
准备配置好的自己的私钥和支付包的公钥
下载支付包的SDK, 安装到自己的虚拟环境里
传参数order_id 返回参数alipay_url
验证用户已经登陆
获取订单对象
调用支付包的SDK (aliPay), 构造支付包支付链接,
把拼接好的url返回前端, 前端对该地址发起请求访问支付包发起支付请求
支付完成后
跳转地址的拼接字符串里面拿到支付宝流水号
传入后端---查询字符串, 调用SDK访问
成功后Payment模型类对应模型类创建对象, 绑定 order_id 和 支付包流水号
订单信息类改变订单状态
-----------------xadmin
--------------restful
每一个url都代表了一种资源
客户端和服务器端传递这种资源的某种表现层
客户端通过四个不同的http请求动词, 操作服务器资源实现‘表现层状态转化’
购物车
购物车的操作 cart/
购物车全选 cart/selection
图片验证码
GET image_code/(?P<image_code_id>[\w-]+)/
短信验证码
GET sms_code/(?P<mobile>1[3-9]\d{9})/?image_code_id=xxx&test=xxx
判断账号是否存在
GET username/(?P<username>\w{5,20})/count
注册
POST users/
登陆
POST authoriaztions/
QQ登陆
GET oauth/qq/autoraztion/?next=xxx
保存邮箱并发送验证邮件
PUT email/
GET emails/verification/?token=xxx
购物车增删改查
GET/POST/PUT/DELETE cart/
购物车全选
PUT cart/selection
生成订单
GET orders/settlement/
提交订单
POST orders/
支付接口
GET orders/(?P<order_id>\d+)/payment/