drf框架之 路飞学城(第二天)
1.第二天的项目是用户购物的数据存入到购物车中,这样保存的数据是存放在redis中
1. 首先先配置redis的数据库链接:
#注意, 数据从redis中获取到的内容,最原始的是二进制形式的数据,想要使用就需要json.loads下 不然无法使用!记住
# redis配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100}
# "PASSWORD": "123",
}
}
}
在settings中做配置:连接redis用
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from api import models
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
token=request.GET.get('token') ret=models.Token.objects.filter(key=token).first()
if ret:
return ret.user,token
else:
raise AuthenticationFailed('您没有登录,请先登录')
写一个认证组件,给后面购物车使用,登录才能添加购物车内容
from rest_framework.response import Response
from rest_framework.views import APIView
from api import models
from api.utils.commonutils import LuffyResponse
from api.utils.commonutils import CommonException from api.luffyserializers import Courseserializers
from api.luffyserializers import CoursesDetailSerializers
from rest_framework.viewsets import ViewSetMixin
from django.core.exceptions import ObjectDoesNotExist from django_redis import get_redis_connection import json
from api.utils.MyAuth import LoginAuth #购物车需要登录之后才能操作(认证组件)
class ShoppingView(APIView):
authentication_classes=[LoginAuth]
conn=get_redis_connection()
def post(self,request):
response=LuffyResponse()
try:
course_in_id=request.data.get('course_id')
policy_in_id=request.data.get('policy_id')
# 1 查询课程是否存在
course=models.Course.objects.get(pk=course_in_id)
#2 获取所有价格策略
policy_list=course.price_policy.all()
#3 取出当前用户购物车的数据
shopping_cart_dic_bytes=self.conn.get('shopping_card_%s'%request.user.id)
#json可以loadsbytes格式
shopping_cart_dic=json.loads(shopping_cart_dic_bytes) if shopping_cart_dic_bytes else {} #注意,从redis中获取数据的是json形式的
# if shopping_cart_dic_bytes:
# shopping_cart_dic=json.loads(shopping_cart_dic_bytes)
# else:
# shopping_cart_dic={} #4 循环价格策略
policy_dict={}
for policy in policy_list:
policy_dict[str(policy.pk)]={
'period':policy.valid_period,
'period_display':policy.get_valid_period_display(),
'price':policy.price }
#5 校验价格策略是否是该课程的价格策略
if policy_in_id not in policy_dict:
raise CommonException('你是爬虫,价格策略不合法')
#6 构造购物车的字典
# shopping_cart_dic[str(course.pk)]
shopping_cart_dic[course_in_id]={
'title':course.name,
'img':course.course_img,
'default_policy':policy_in_id,
'policy':policy_dict
}
#7 存入redis
self.conn.set('shopping_card_%s'%request.user.id,json.dumps(shopping_cart_dic))
#使用的是字符串形式存入redis中,=
response.msg='加入购物车成功' except CommonException as e:
response.status = 102
response.msg = e.msg
except ObjectDoesNotExist as e:
response.status = 101
response.msg = '您要加入购物车的课程不存在'
except Exception as e:
response.status=105
response.msg=str(e)
return Response(response.get_dic) def get(self,request): #注意这里的获取数据是通过redis来获取得到的
response = LuffyResponse()
shopping_cart_dic_bytes = self.conn.get('shopping_card_%s' % request.user.id)
shopping_cart_dic = json.loads(shopping_cart_dic_bytes) if shopping_cart_dic_bytes else {}
response.data=shopping_cart_dic
response.msg='查询成功' return Response(response.get_dic) def delete(self,request):
#传入的数据格式{"course_id":"1"}
course_in_id=request.data.get('course_id')
response = LuffyResponse()
shopping_cart_dic_bytes = self.conn.get('shopping_card_%s' % request.user.id)
#获取是那个用户, 并给这个用户反序列化拿到字典形式的数据
shopping_cart_dic = json.loads(shopping_cart_dic_bytes) if shopping_cart_dic_bytes else {}
#从反序列化后的字典 并踢出用户提交出来的数据
shopping_cart_dic.pop(course_in_id)
#保存到redis中
self.conn.set('shopping_card_%s' % request.user.id, json.dumps(shopping_cart_dic))
response.msg = '删除成功'
return Response(response.get_dic) def put(self,request): course_in_id=request.data.get('course_id') #课程ID
policy_in_id=request.data.get('policy_id') #价格策略ID
response = LuffyResponse()
try:
shopping_cart_dic_bytes = self.conn.get('shopping_card_%s' % request.user.id)
#获取用户购物车内的数据注意是二进制形式
shopping_cart_dic = json.loads(shopping_cart_dic_bytes) if shopping_cart_dic_bytes else {}
#取出该课程所有的价格策略
policy=shopping_cart_dic[course_in_id]['policy']
if policy_in_id not in policy:
raise CommonException('传入的价格策略非法,你可能是爬虫')
shopping_cart_dic[course_in_id]['default_policy']=policy_in_id #保存到redis中
self.conn.set('shopping_card_%s' % request.user.id, json.dumps(shopping_cart_dic))
response.msg='修改成功' except CommonException as e:
response.status = 102
response.msg = e.msg
except Exception as e:
response.status=105
response.msg=str(e)
return Response(response.get_dic)
购物车的逻辑代码, 取从redis获取,拿也是从redis中拿
from rest_framework.response import Response
from rest_framework.views import APIView
from api import models
from api.utils.commonutils import LuffyResponse
from api.utils.commonutils import CommonException from api.luffyserializers import Courseserializers
from api.luffyserializers import CoursesDetailSerializers
from rest_framework.viewsets import ViewSetMixin
from django.core.exceptions import ObjectDoesNotExist from django_redis import get_redis_connection
import datetime
import json
from api.utils.MyAuth import LoginAuth
import time
#结算中心
class PaymentView(APIView):
conn=get_redis_connection()
authentication_classes=[LoginAuth]
def post(self,request):
#{"course_list":[{"course_id":"1","policy_id":"1"},{"course_id":"2","policy_id":"2"}]}
response = LuffyResponse()
course_in_list=request.data.get('course_list')
try:
# 1 定义结算中心的字典,定义全局优惠券的字典
payment_dict_userid = {}
global_coupon_dict = {
"coupon": {},
"default_coupon": 0
}
#2 拿到购物车,循环取出传入的课程id,判断是否在购物车中,不在直接抛异常
shopping_cart_dic_bytes = self.conn.get('shopping_card_%s' % request.user.id)
# json可以loadsbytes格式
shopping_cart_dic = json.loads(shopping_cart_dic_bytes) if shopping_cart_dic_bytes else {}
for course_in in course_in_list:
course_in_id=course_in.get('course_id')
if course_in_id not in shopping_cart_dic:
raise CommonException('要结算的课程不合法,不在购物车中')
#3 构造单个课程详情的字典,把购物车中的当前课程,update到该字典中
course_detail = {
'coupon': {},
'default_coupon':''
#....课程详情的数据
}
course_detail.update(shopping_cart_dic[course_in_id])
#4 将该课程详情,加入到结算中心
payment_dict_userid[course_in_id]=course_detail
#5 一次性查出当前用户的所有优惠券信息(用户为当前用户,状态为未使用,优惠券起始时间小于当前时间,优惠券结束时间大于当前时间)
#获取当前时间
ctime = datetime.datetime.today().strftime('%Y-%m-%d')
print(ctime)
#查询此人所有可用优惠券
coupon_list = models.CouponRecord.objects.filter(
user=request.user,
status=0,
coupon__valid_begin_date__lte=ctime,
coupon__valid_end_date__gte=ctime,
)
#6 循环所有优惠券
for item in coupon_list:
#7 构造出单个优惠券的空字典,拿到优惠券类型(1立减 2 满减 3折扣),拿到优惠券id,拿到该优惠券绑定的课程id(有可能为空)
coupon_detail = {}
#优惠券类型
coupon_type=item.coupon.coupon_type
#优惠券id
coupon_id=item.pk
#该优惠券绑定的课程id(根据这个字段判断是全站优惠券还是课程优惠券)
course_id=item.coupon.object_id
#8 构造单个优惠券字典,将数据填充进去
coupon_detail['coupon_type'] = coupon_type
coupon_detail['coupon_display'] = item.coupon.get_coupon_type_display()
if coupon_type == 0: # 立减券,构造出等值金额
coupon_detail['money_equivalent_value'] = item.coupon.money_equivalent_value
elif coupon_type == 1: # 满减券,构造出等值金额,和最低消费金额
coupon_detail['money_equivalent_value'] = item.coupon.money_equivalent_value
coupon_detail['minimum_consume'] = item.coupon.minimum_consume
else: # 其他情况,构造出打折(如打八折,80)
coupon_detail['off_percent'] = item.coupon.off_percent #9 判断是全站优惠券还是课程优惠券
if not course_id:
#课程id为空,放到全站优惠券大字典中
global_coupon_dict['coupon'][str(coupon_id)]=coupon_detail
else:
#课程优惠券
coupon_course_id = str(course_id)
if coupon_course_id not in payment_dict_userid: # 当前课程优惠券对应的可能如果不在结算中心字典里,continue
continue
# 在结算中心字典中的,对应放入到课程优惠券字段上
payment_dict_userid[str(coupon_course_id)]['coupon'][str(coupon_id)] = coupon_detail # 10讲结算中心字典和全局优惠券字典,放入redis中
self.conn.set('payment_dict_%s'%request.user.id,json.dumps(payment_dict_userid))
self.conn.set('global_coupon_dict_%s'%request.user.id,json.dumps(global_coupon_dict))
response.msg='加入结算中心成功' except CommonException as e:
response.status = 102
response.msg = e.msg
except Exception as e:
response.status = 105
response.msg = str(e)
return Response(response.get_dic) def get(self,request):
response=LuffyResponse()
payment_dic_bytes=self.conn.get('payment_dict_%s'%request.user.id)
global_coupon_dict_bytes=self.conn.get('global_coupon_dict_%s'%request.user.id)
payment_dic= json.loads(payment_dic_bytes) if payment_dic_bytes else {}
global_coupon_dict= json.loads(global_coupon_dict_bytes) if global_coupon_dict_bytes else {}
response.msg='查询成功'
response.data={
'payment':payment_dic,
'global_coupon':global_coupon_dict
}
return Response(response.get_dic) class PayFinal(APIView):
conn=get_redis_connection()
authentication_classes=[LoginAuth]
def post(self,request):
#传入的数据格式
# {
# "price": 600
# "bely": 100
# }
response = LuffyResponse() try:
price_in = request.data.get('price')
bely = request.data.get('bely')
#1从结算中心拿出字典,全局优惠券字典取出来
payment_dic_bytes=self.conn.get('payment_dict_%s' % request.user.id)
payment_dic=json.loads(payment_dic_bytes) if payment_dic_bytes else {}
global_coupon_dic_bytes=self.conn.get('payment_dict_%s' % request.user.id)
global_coupon_dic=json.loads(global_coupon_dic_bytes) if global_coupon_dic_bytes else {} price_list=[]
#2 循环结算中心字典,得到课程和课程id
for course_id,course_detail in payment_dic.items():
# 3取出默认价格策略,取出默认价格,取出默认优惠券id
default_policy_id=course_detail['default_policy']
default_price=course_detail['policy'][default_policy_id]['price']
default_coupon_id=course_detail['default_coupon']
#4 判断如果默认优惠券不为0,
# 表示使用了优惠券:
# 取出默认优惠券的字典,
# 调用计算价格函数得到价格,把价格放到价格列表中(后面直接用sum函数计算总价格)
if default_coupon_id!=0:
#使用了优惠券
default_coupon_detail=course_detail['coupon'][default_coupon_id]
#调用计算价格的函数
default_price=self.account(default_price,default_coupon_detail)
price_list.append(default_price)
#5 取出全局默认优惠券id,根据默认优惠券id取出全局优惠券字典,调用计算价格函数得到实际支付价格
global_coupon_id=global_coupon_dic['default_coupon']
if global_coupon_id!=0:
global_coupon_detail=global_coupon_dic['coupon'][str(global_coupon_id)]
final_price=self.account(sum(price_list),global_coupon_detail)
else:
final_price=sum(price_list) #6判断贝利数大于传入的贝利数,
# 用实际价格减去贝利数,如果得到结果小于0,
# 直接等于0,判断最终价格和传如的价格是否相等,
# 不相等抛异常
if not request.user.beli>=bely:
raise CommonException('贝利数不合法')
final_price=final_price-bely/10
if final_price<0:
final_price=0 if final_price !=price_in:
raise CommonException('传入的价格不合法')
if final_price>0:
#构造支付宝支付
# 拼凑支付宝url
alipay = ali()
# 生成支付的url
query_params = alipay.direct_pay(
subject="路飞学成课程", # 商品简单描述
out_trade_no="x2" + str(time.time()), # 商户订单号
total_amount=final_price, # 交易金额(单位: 元 保留俩位小数)
)
pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
response.url = pay_url except CommonException as e:
response.status = 102
response.msg = e.msg
except Exception as e:
response.status = 105
response.msg = str(e)
return Response(response.get_dic) def account(self,price,coupon_dic):
# 设置总价格为price
total_price = price
# 取出优惠券类型
coupon_type = coupon_dic['coupon_type']
# 优惠券类型是0,立减
if coupon_type == 0:
total_price = price - coupon_dic['money_equivalent_value'] ##优惠券类型是1,满减,必须大于最低消费金额
elif coupon_type == 1:
if price >= coupon_dic['minimum_consume']:
total_price = price - coupon_dic['money_equivalent_value']
else:
raise CommonException('优惠券不满足最低使用金额')
##优惠券类型是2,直接打折
elif coupon_type == 2:
total_price = price * coupon_dic['off_percent'] / 100 return total_price
支付功能实现
drf框架之 路飞学城(第二天)的更多相关文章
- drf框架使用之 路飞学城(第一天)
1. 路飞学城第一天: 知识点 使用的是序列化与反序列化的使用: 1.创建一个公共相应的Json方法: #创建一个公共响应的类: class LuffyResponse(): def __init__ ...
- 路飞学城—Python爬虫实战密训班 第二章
路飞学城—Python爬虫实战密训班 第二章 一.Selenium基础 Selenium是一个第三方模块,可以完全模拟用户在浏览器上操作(相当于在浏览器上点点点). 1.安装 - pip instal ...
- django环境部署 crm和路飞学城
环境依赖 yum install gcc patch libffi-devel python-devel zlib-devel bzip2-devel openssl-devel ncurses-de ...
- linux vue uwsgi nginx 部署路飞学城 安装 vue
vue+uwsgi+nginx部署路飞学城 有一天,老男孩的苑日天给我发来了两个神秘代码,听说是和mjj的结晶 超哥将这两个代码,放到了一个网站上,大家可以自行下载 路飞学城django代码#这个代码 ...
- python 全栈开发,Day98(路飞学城背景,django ContentType组件,表结构讲解)
昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...
- 路飞学城Python-Day59(第五模块复习题)
HTML div标签是块级标签,单独一行,可以作为其他标签的容器,没有特定含义 span是内联标签,可以作为文本内容的容器,没有特定含义 1. 查询一下对div和span标签的理解 不同的标签有自己含 ...
- 路飞学城Python-Day59(第五模块记录)
HTML部分 <!DOCTYPE html> <html lang="en"> <head> <!--head标签的主要作用:文档的头部主 ...
- 路飞学城Python-Day53
01-jquery的介绍 JS在做项目或者是实现功能的时候,用JS去操作DOM元素非常复杂,代码量大,重复性代码也多 多个元素使用for循环遍历也是非常麻烦的,对于JS使用来说加大了难度 jQuery ...
- day75:luffy:路飞学城项目后端环境搭建&Git相关知识点
目录 1.Xadmin 1.Xadmin介绍 2.Xadmin安装 3.Xadmin的使用 2.项目环境搭建 1.外部依赖 2.依赖包安装 3.搭建项目 3.Git 4.日志配置 5.异常处理 6.创 ...
随机推荐
- 连接管理 与 Netty 心跳机制
一.前言 踏踏实实,动手去做,talk is cheap, show me the code.先介绍下基础知识,然后做个心跳机制的Demo. 二.连接 长连接:在整个通讯过程,客户端和服务端只用一个S ...
- Java_04循环结构
1.while 循环结构 格式: while(循环条件){ } 关键字 while 后的小括号中的内容是循环条件.循环条件是一个表达式,值为布尔类型. { }大括号中的语句统称为循环操作,又称为循环体 ...
- apache做反向代理
实验目的 通过apache实现反向代理的功能,类似nginx反向代理和haproxy反向代理 环境准备 逻辑架构如下 前端是apche服务器,监听80端口,后端有两台web服务器,分别是node1和n ...
- Unity 3D类结构简介
趁着周末,再来一发.对于Unity3D,我也是刚开始学习,希望能够与大家多多交流.好了,废话不多说,下面继续. 本篇文章使用C#进行举例和说明.关于Unity 3D编辑器中的各种窗口,网上有很多资料了 ...
- Azure CosmosDB (10) Azure Cosmos DB体系结构
<Windows Azure Platform 系列文章目录> Azure Cosmos DB的体系结构分为以下几个部分: 1.Database Accounts Database Acc ...
- RDMS三剑客的服务
@echo off title %1 goto %1 echo Error... echo. goto bexit :orcl_stop rem 顺序:EM.LSN.SID rem echo stop ...
- Linux 调试打印时间和颜色
Linux调试打印时间和颜色 #include <sys/time.h> #include <unistd.h> void print_time(void) { struct ...
- 报错:Flink Could not resolve substitution to a value: ${akka.stream.materializer}
报错现象: Exception in thread "main" com.typesafe.config.ConfigException$UnresolvedSubstitutio ...
- ActiveMQ(为什么要使用消息中间件,JMS传输模型)
为什么要使用消息中间件: 同步请求:当客户端向服务器发送一条请求的时候,此时服务器由于网络,或者处理一些比较大的数据的时候,可能有延迟,客户端 会处于一直等待的状态.只有等待服务器返回处理结果, ...
- tab$被删除恢复指南
by 蔡建良 2019-2-25 经过长时间摸索,参考网上各类文章.今天终于让我成功恢复了oracle的sys.tab$表,并成功打开了数据库. 将此过程记录下来,与大家共享.如有疑问可联系我QQ: ...