2018-11-15 17:43:50

还有一点路飞项目就结束啦!

周日打算回去!

双十一的耳机到啦,音质确实不错!2333!

等着项目做完,完整总结一下!

越努力,越幸运!永远不要高估自己!!!!

贴上源码!

今天老师实现了结算中心 显示课程,修改优惠券和其他的东西

整体逻辑不难,思路清晰,易于理解

payment.py

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.utils.auth import LuffyAuth
from django.conf import settings
from django_redis import get_redis_connection
import json
from app01.utils.response import BaseResponse
from app01 import models
import datetime class PaymentViewSet(APIView):
authentication_classes = [LuffyAuth, ]
conn = get_redis_connection("default") def post(self, request, *args, **kwargs):
"""
获取用户要结算的课程和优惠券
:param request:
:param args:
:param kwargs:
:return:
"""
ret = BaseResponse()
try:
# 清空当前用户结算中心的数据
# luffy_payment_1_*
# luffy_payment_coupon_1
key_list = self.conn.keys(settings.PAYMENT_KEY % (request.auth.user_id, "*",))
key_list.append(settings.PAYMENT_COUPON_KEY % (request.auth.user_id,))
self.conn.delete(*key_list)
payment_dict = {}
global_coupon_dict = {
"coupon": {},
"default_coupon": 0
}
# 1. 获取用户要结算课程ID
course_id_list = request.data.get('courseids')
for course_id in course_id_list:
car_key = settings.SHOPPING_CAR_KEY % (request.auth.user_id, course_id,) # 1.1 检测用户要结算的课程是否已经加入购物车
if not self.conn.exists(car_key):
ret.code = 1001
ret.error = "课程需要先加入购物车才能结算"
# 1.2 从购物车中获取信息,放入到结算中心。
# 获取标题和图片
policy = json.loads(self.conn.hget(car_key, 'policy').decode('utf-8'))
default_policy = self.conn.hget(car_key, 'default_policy').decode('utf-8')
policy_info = policy[default_policy] payment_course_dict = {
"course_id": str(course_id),
"title": self.conn.hget(car_key, 'title').decode('utf-8'),
"img": self.conn.hget(car_key, 'img').decode('utf-8'),
"policy_id": default_policy,
"coupon": {},
"default_coupon": 0
}
payment_course_dict.update(policy_info)
payment_dict[str(course_id)] = payment_course_dict
# 2. 获取优惠券
ctime = datetime.date.today()
coupon_list = models.CouponRecord.objects.filter(
account=request.auth.user,
status=0,
coupon__valid_begin_date__lte=ctime,
coupon__valid_end_date__gte=ctime,
)
for item in coupon_list: # 只处理绑定课程的优惠券
if not item.coupon.object_id:
# 优惠券ID
coupon_id = item.id # 优惠券类型:满减、折扣、立减
coupon_type = item.coupon.coupon_type info = {}
info['coupon_type'] = coupon_type
info['coupon_display'] = item.coupon.get_coupon_type_display()
if coupon_type == 0: # 立减
info['money_equivalent_value'] = item.coupon.money_equivalent_value
elif coupon_type == 1: # 满减券
info['money_equivalent_value'] = item.coupon.money_equivalent_value
info['minimum_consume'] = item.coupon.minimum_consume
else: # 折扣
info['off_percent'] = item.coupon.off_percent global_coupon_dict['coupon'][coupon_id] = info continue
# 优惠券绑定课程的ID
coupon_course_id = str(item.coupon.object_id) # 优惠券ID
coupon_id = item.id # 优惠券类型:满减、折扣、立减
coupon_type = item.coupon.coupon_type info = {}
info['coupon_type'] = coupon_type
info['coupon_display'] = item.coupon.get_coupon_type_display()
if coupon_type == 0: # 立减
info['money_equivalent_value'] = item.coupon.money_equivalent_value
elif coupon_type == 1: # 满减券
info['money_equivalent_value'] = item.coupon.money_equivalent_value
info['minimum_consume'] = item.coupon.minimum_consume
else: # 折扣
info['off_percent'] = item.coupon.off_percent if coupon_course_id not in payment_dict:
# 获取到优惠券,但是没有购买此课程
continue
# 将优惠券设置到指定的课程字典中
payment_dict[coupon_course_id]['coupon'][coupon_id] = info
# 可以获取绑定的优惠券
# 3. 将绑定优惠券课程+全站优惠券 写入到redis中(结算中心)。
# 3.1 绑定优惠券课程放入redis
for cid, cinfo in payment_dict.items():
pay_key = settings.PAYMENT_KEY % (request.auth.user_id, cid,)
cinfo['coupon'] = json.dumps(cinfo['coupon'])
self.conn.hmset(pay_key, cinfo)
# 3.2 将全站优惠券写入redis
gcoupon_key = settings.PAYMENT_COUPON_KEY % (request.auth.user_id,)
global_coupon_dict['coupon'] = json.dumps(global_coupon_dict['coupon'])
self.conn.hmset(gcoupon_key, global_coupon_dict) except Exception as e:
pass return Response(ret.dict) def patch(self, request, *args, **kwargs):
"""
修改优惠券
:param request:
:param args:
:param kwargs:
:return:
"""
ret = BaseResponse()
try:
# 1. 用户提交要修改的优惠券
course = request.data.get('courseid')
course_id = str(course) if course else course coupon_id = str(request.data.get('couponid')) # payment_global_coupon_1
redis_global_coupon_key = settings.PAYMENT_COUPON_KEY % (request.auth.user_id,) # 修改全站优惠券
if not course_id:
if coupon_id == "":
# 不使用优惠券,请求数据:{"couponid":0}
self.conn.hset(redis_global_coupon_key, 'default_coupon', coupon_id)
ret.data = "修改成功"
return Response(ret.dict)
# 使用优惠券,请求数据:{"couponid":2}
coupon_dict = json.loads(self.conn.hget(redis_global_coupon_key, 'coupon').decode('utf-8')) # 判断用户选择得优惠券是否合法
if coupon_id not in coupon_dict:
ret.code = 1001
ret.error = "全站优惠券不存在"
return Response(ret.dict) # 选择的优惠券合法
self.conn.hset(redis_global_coupon_key, 'default_coupon', coupon_id)
ret.data = "修改成功"
return Response(ret.dict) # 修改课程优惠券
# luffy_payment_1_1
redis_payment_key = settings.PAYMENT_KEY % (request.auth.user_id, course_id,)
# 不使用优惠券
if coupon_id == "":
self.conn.hset(redis_payment_key, 'default_coupon', coupon_id)
ret.data = "修改成功"
return Response(ret.dict) # 使用优惠券
coupon_dict = json.loads(self.conn.hget(redis_payment_key, 'coupon').decode('utf-8'))
if coupon_id not in coupon_dict:
ret.code = 1010
ret.error = "课程优惠券不存在"
return Response(ret.dict) self.conn.hset(redis_payment_key, 'default_coupon', coupon_id) except Exception as e:
ret.code = 1111
ret.error = "修改失败" return Response(ret.dict) def get(self, request, *args, **kwargs):
"""
结算中心展示页面(用户访问)
:param request:
:param args:
:param kwargs:
:return:
"""
ret = BaseResponse()
try:
# luffy_payment_1_*
redis_payment_key = settings.PAYMENT_KEY % (request.auth.user_id, "*",)
# luffy_payment_coupon_1
redis_global_coupon_key = settings.PAYMENT_COUPON_KEY % (request.auth.user_id,)
# 1. 获取绑定课程信息
course_list = []
for key in self.conn.scan_iter(redis_payment_key):
info = {}
data = self.conn.hgetall(key)
for k, v in data.items():
kk = k.decode('utf-8')
if kk == "coupon":
info[kk] = json.loads(v.decode('utf-8'))
else:
info[kk] = v.decode('utf-8')
course_list.append(info) # 2.全站优惠券
global_coupon_dict = {
'coupon': json.loads(self.conn.hget(redis_global_coupon_key, 'coupon').decode('utf-8')),
'default_coupon': self.conn.hget(redis_global_coupon_key, 'default_coupon').decode('utf-8')
} ret.data = {
"course_list": course_list,
"global_coupon_dict": global_coupon_dict
}
except Exception as e:
ret.code = 1001
ret.error = "获取失败" return Response(ret.dict)

放上笔记

s9day113 

内容回顾:
1. 路飞学城的购物车如何实现? 2. 商品是否有个数?
- 价格策略(用事件来类比个数)
- 购买之后就开始计时 3. 购物车在redis的结构? 4. 购物车购买数量有限制吗?
.keys('xxxxx')
5. 购物车是否设置超时时间?
.conn.expire("shopping_car_1_1" ,60*30) 方案:购买课程个数限制(200个) 6. 为什么把购物车信息放入redis?
- 临时状态
- 频繁修改的话,速度快。 7. 具体购物车的逻辑?
添加:
1. 用户选择:课程、价格策略,提交
2. 获取课程、价格策略进行合法性校验(数据库查询)
3. 数据获取,构造结构:
{
shopping_car_用户ID_课程ID:{
title:"...",
img:'xxx',
policy:{
...
}
}
}
4. 将数据以字典的形式保存到redis中。
修改:
1. 用户选择:课程、价格策略,提交
2. 获取课程、价格策略进行合法性校验(redis查询)
3. 更新价格策略
删除:
1. 用户选择:课程提交
2. 获取课程合法性校验(redis查询)
3. 删除
查看:
1. 构造Key shopping_car_用户ID_*
2. scan_iter 8. 原则:
- 简答逻辑先处理
- try
- 细粒度异常+自定义异常
- 导入模块
- 内置
- 框架
- 自定义
- 注释
- 文件
- 类
- 函数
- 文件名、类、函数、project
- 对功能进行分类
- 减少代码层级
- BaseResponse 今日内容:
- 结算中心
- 去支付 内容详细:
1. 结算中心
a. 添加到结算中心:
请求:POST
数据:
{
courseids:[1,2]
} Q补充:
con = {
"id":1,
"age__gt":9,
"name__lt": 8
"name__lt": 8
} # 构造AND
models.User.objects.filter(**con) # 构造复杂(条件写死)
con = Q(Q(account=request.auth.user) & Q(status=0)) | Q(coupon__valid_begin_date__lte=ctime)
models.User.objects.filter(con) # 构造负责(条件动态)
q1 = Q()
q1.connector = 'OR'
for k,v in con.items():
q1.children.append((k,v,))
models.User.objects.filter(q1) 结算数据及目标:
payment_dict = {
'': {
course_id:2,
'title': 'CRM客户关系管理系统实战开发-专题',
'img': 'CRM.jpg', 'policy_id': '',
'coupon': {},
'default_coupon': 0,
'period': 210, 'period_display': '12个月', 'price': 122.0},
'': {
course_id:2,
'title': '爬虫开发-专题',
'img': '爬虫开发-专题.jpg',
'policy_id': '',
'coupon': {
4: {'coupon_type': 0, 'coupon_display': '立减券', 'money_equivalent_value': 40},
6: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 60, 'minimum_consume': 100}
},
'default_coupon': 0,
'period': 60,
'period_display': '2个月',
'price': 599.0}
} global_coupon_dict = {
'coupon': {
2: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 200, 'minimum_consume': 500}
},
'default_coupon': 0
}
========================================= redis ==============================================
redis = {
payment_1_2:{
course_id:2,
'title': 'CRM客户关系管理系统实战开发-专题',
'img': 'CRM.jpg', 'policy_id': '',
'coupon': {},
'default_coupon': 0,
'period': 210, 'period_display': '12个月', 'price': 122.0},
},
payment_1_1:{
course_id:1,
'title': '爬虫开发-专题',
'img': '爬虫开发-专题.jpg',
'policy_id': '',
'coupon': {
4: {'coupon_type': 0, 'coupon_display': '立减券', 'money_equivalent_value': 40},
6: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 60, 'minimum_consume': 100}
},
'default_coupon': 0,
'period': 60,
'period_display': '2个月',
'price': 599.0}
},
payment_global_coupon_1:{
'coupon': {
2: {'coupon_type': 1, 'coupon_display': '满减券', 'money_equivalent_value': 200, 'minimum_consume': 500}
},
'default_coupon': 0
}
}

11.15luffycity(7)的更多相关文章

  1. 地区sql

    /*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50136Source Host : lo ...

  2. WinForm 天猫2013双11自动抢红包【源码下载】

    1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...

  3. C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)

    #include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...

  4. CSS垂直居中的11种实现方式

    今天是邓呆呆球衣退役的日子,在这个颇具纪念意义的日子里我写下自己的第一篇博客,还望前辈们多多提携,多多指教! 接下来,就进入正文,来说说关于垂直居中的事.(以下这11种垂直居中的实现方式均为笔者在日常 ...

  5. C++ 11 多线程--线程管理

    说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...

  6. CSharpGL(11)用C#直接编写GLSL程序

    CSharpGL(11)用C#直接编写GLSL程序 +BIT祝威+悄悄在此留下版了个权的信息说: 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharp ...

  7. ABP(现代ASP.NET样板开发框架)系列之11、ABP领域层——仓储(Repositories)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之11.ABP领域层——仓储(Repositories) ABP是“ASP.NET Boilerplate Proj ...

  8. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  9. C++11网络编程

    Handy是一个简洁优雅的C++11网络库,适用于linux与Mac平台.十行代码即可完成一个完整的网络服务器. 下面是echo服务器的代码: #include <handy/handy.h&g ...

随机推荐

  1. sqlserver数据库出现可疑错误修复方法

    一.主数据库出现可疑修复方法: 第一种方法: 当数据库发生这种操作故障时,可以按如下操作步骤可处理此要领,打开数据库里的Sql查询编辑器窗口,运行以下的命令: ?修改数据库为紧急模式 ALTER DA ...

  2. ASP.NET Core 中的文件上传

    ASP.NET Core上传文件 ASP.NET Core使用IFormFile来读取上传的文件内容,然后将数据写入到磁盘或其它存储空间. 添加FileUpload模型,用来接收上传的文件内容. pu ...

  3. Creating an LMDB database in Python

    LMDB is the database of choice when using Caffe with large datasets. This is a tutorial of how to cr ...

  4. CentOS ISO版本区别

    CentOS6 CentOS7 介绍 区别 bin-DVD.iso bin-DVD.iso 系统标准安装包 bin DVD本身包含了软件,不需要依赖于网络经行安装. bin-DVD2.iso Ever ...

  5. Tone Mapping算法系列二:一种自适应对数映射的高对比度图像显示技术及其速度优化。

    办公室今天停电,幸好本本还有电,同事们好多都去打麻将去了,话说麻将这东西玩起来也还是有味的,不过我感觉我是输了不舒服,赢了替输的人不舒服,所以干脆拜别麻坛四五年了,在办公室一个人整理下好久前的一片论文 ...

  6. KVM之CPU虚拟化

    1.1 为什么要虚拟化CPU 虚拟化技术是指在x86的系统中,一个或以上的客操作系统(Guest Operating System,简称:Guest OS)在一个主操作系统(Host Operatin ...

  7. BABLE 原理

    1.babel转换原理 2.主要过程 (1)babylon进行解析得到AST (2)babel-traverse插件对AST树进行遍历转译得到新的AST树 (3)babel-generator将AST ...

  8. php : 文件及文件夹操作(创建、删除、移动、复制)

    Talk is cheap, show you the code : <?php /** * 操纵文件类 * */ class FileUtil { /** * 建立文件夹 * * @param ...

  9. GIT里的一些名词

    origin:他是一个特定远程仓库的别名,他不是一个仓库的属性. head:通常情况下可以将它与当前的分支等同.

  10. python 奇偶拆分list,python拆分list,得到一个原来list的奇数list,一个原来list的偶数list

    需求:现在有一个list ,range_data = ['m', 'M', 'h', 'c', 'X', 'Z', 'A', 'o'] 希望得到两个list,  一个是奇数list =['m', 'h ...