Django-discount策略解耦实现

  • 模型设计
  • 模型代码
  • 具体实现

模型设计

之前一直以为物品的discount策略会放到前端做来做判断,直到视频到这个阶段,才发现是在后端做判断,而且各种策略是存放在数据表格中的,很妙!直接看一下表格设计,如下图:

要实现discount策略我们需要新建四个表:

  1. discount类型表:存放discount的具体类型
  2. price策略表:存放discount类型对应的计算方法,discount类型作为外键
  3. discount活动:存放一个活动的名称,开始、结束时间
  4. 关系表:课程与discount以及活动之间的关系
    这样设计,我们在查询一个课程的时候,我们能够获得discount的策略、discount的类型、discount活动的名称信息,方便对课程的价格进行相应策略计算。

模型代码

"""价格相关的模型"""
class CourseDiscountType(BaseModel):"""课程优惠类型"""name = models.CharField(max_length=32, verbose_name="优惠类型名称")remark = models.CharField(max_length=250, blank=True, null=True, verbose_name="备注信息")class Meta:db_table = "ly_course_discount_type"verbose_name = "课程优惠类型"verbose_name_plural = "课程优惠类型"def __str__(self):return "%s" % (self.name)class CourseDiscount(BaseModel):"""课程优惠模型"""discount_type = models.ForeignKey("CourseDiscountType", on_delete=models.CASCADE, related_name='coursediscounts',verbose_name="优惠类型")condition = models.IntegerField(blank=True, default=0, verbose_name="满足优惠的价格条件",help_text="设置参与优惠的价格门槛,表示商品必须在xx价格以上的时候才参与优惠活动,<br>如果不填,则不设置门槛")sale = models.TextField(verbose_name="优惠公式",blank=True,null=True, help_text="""不填表示免费;<br>*号开头表示折扣价,例如*0.82表示八二折;<br>-号开头则表示减免,例如-20表示原价-20;<br>如果需要表示满减,则需要使用 原价-优惠价格,例如表示课程价格大于100,优惠10;大于200,优惠20,格式如下:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;满100-10<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;满200-25<br>""")class Meta:db_table = "ly_course_discount"verbose_name = "价格优惠策略"verbose_name_plural = "价格优惠策略"def __str__(self):return "价格优惠:%s,优惠条件:%s,优惠值:%s" % (self.discount_type.name, self.condition, self.sale)class Activity(BaseModel):"""优惠活动"""name = models.CharField(max_length=150, verbose_name="活动名称")start_time = models.DateTimeField(verbose_name="优惠策略的开始时间")end_time = models.DateTimeField(verbose_name="优惠策略的结束时间")remark = models.CharField(max_length=250, blank=True, null=True, verbose_name="备注信息")class Meta:db_table = "ly_activity"verbose_name="商品活动"verbose_name_plural="商品活动"def __str__(self):return self.nameclass CoursePriceDiscount(BaseModel):"""课程与优惠策略的关系表"""course = models.ForeignKey("Course",on_delete=models.CASCADE, related_name="activeprices",verbose_name="课程")active = models.ForeignKey("Activity",on_delete=models.DO_NOTHING, related_name="activecourses",verbose_name="活动")discount = models.ForeignKey("CourseDiscount",on_delete=models.CASCADE,related_name="discountcourse",verbose_name="优惠折扣")class Meta:db_table = "ly_course_price_dicount"verbose_name="课程与优惠策略的关系表"verbose_name_plural="课程与优惠策略的关系表"def __str__(self):return "课程:%s,优惠活动: %s,开始时间:%s,结束时间:%s" % (self.course.name, self.active.name, self.active.start_time,self.active.end_time)

写好模型代码之后需要进行数据迁移和xadmin注册,这里就略过。

具体实现

有了上述的模型,我们就可以在想要对价格进行处理的模型中添加下面的一些方法:

@property
def discount_name(self):"""如果商品有参与了活动,则返回折扣类型"""name = ""# 获取当前课程参与的所有活动active_list = self.active_list()if len(active_list) > 0:"""当前课程如果有参与到1个以上活动时才有优惠类型"""active =active_list[0]name = active.discount.discount_type.namereturn namedef active_list(self):"""获取当前课程参与的活动"""return self.activeprices.filter(is_show=True, is_delete=False, active__start_time__lte=datetime.now(),active__end_time__gte=datetime.now()).order_by("-orders", "-id")
@property
def real_price(self):"""课程的真实价格"""# 默认真实为原价price = self.priceactive_list = self.active_list()if len(active_list) > 0:"""如果当前课程有参与了活动"""active = active_list[0]# 参与活动的价格门槛condition = active.discount.conditionsale = active.discount.saleself.price = float(self.price)if self.price >= condition:"""只有原价满足价格门槛才进行优惠计算"""if sale == "":"""限时免费"""price = 0elif sale[0] == "*":"""限时折扣"""price = self.price * float(sale[1:])elif sale[0] == "-":"""限时减免"""if self.price - float(sale[1:]) >= 0:price = self.price - float(sale[1:])elif sale[0] == "满":"""满减"""sale_list = sale.split("\r\n")price_list = [] # 设置一个列表,把当前课程原价满足的满减条件全部保存进去# 把满减的每一个选项在循环中,提取条件价格和课程原价进行判断for sale_item in sale_list:item = sale_item[1:]condition_price,condition_sale = item.split("-")if self.price >= float(condition_price):price_list.append(float(condition_sale) )if self.price - max(price_list) >= 0:price = self.price - max(price_list) # 课程原价 - 最大优惠return "%.2f" % price

有一些值得关注的点,这一段代码:return self.activeprices.filter(is_show=True, is_delete=False, active__start_time__lte=datetime.now(), active__end_time__gte=datetime.now()).order_by("-orders", "-id")

  • 为什么在course表中没有activeprices字段,但是却能够使用self.activeprices?
    因为我们在定义discount与课程关系模型的时候,声明了以course表为外键,并且设置了related_name="activeprices"。这么设置,能够让在主表中直接使用设置的值来查询子表中的信息。这篇博客讲的比较详细https://blog.csdn.net/hpu_yly_bj/article/details/78939748
  • active__end_time__gte是什么意思?
    discount与课程关系模型中有activate字段,而且也是作为这个表的外键,可以通过"_X_"的方法来查询activate中的X字段,而gte又表示大于等于的意思。所以,整句话就是查询活动时间在活动开始时间到活动结束时间之间的课程。

__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于

Django-discount策略解耦实现相关推荐

  1. 测试django_如何像专业人士一样测试Django Signals

    测试django by Haki Benita 通过Haki Benita 如何像专业人士一样测试Django Signals (How to test Django Signals like a p ...

  2. 业务随行:用户的网络访问策略还能这么玩

    本文分享自华为云社区<数通Datacom认证新知识点:业务随行>,原文作者:迷图小书童 . 一.功能特性概述 所谓业务随行,顾名思义,指的是在园区中,无论某个人员如何在网络中移动,从什么地 ...

  3. 人工智能中的rl是什么意思_AI学习如何使用第二部分来创建自定义RL环境并培训代理...

    人工智能中的rl是什么意思 From Icarus burning his wings to the Wright brothers soaring through the sky, it took ...

  4. 流畅的Python阅读笔记(二)

    2021年6月2日--yaco 流畅的Python5-8章内容 第5章:一等函数 在 Python 中,函数是一等对象,编程语言理论家把"一等对象"定义为满 足下述条件的程序实体: ...

  5. 强化学习是针对优化数据的监督学习?

    作者 | Ben Eysenbach.Aviral Kumar.Abhishek Gupta 编译 | 凯隐 出品 | AI科技大本营(ID:rgznai100) 强化学习(RL)可以从两个不同的视角 ...

  6. 《强化学习周刊》第7期:强化学习应用之游戏

    No.07 智源社区 强化学习组 强 化 学  习 研究 观点 资源 活动 关于周刊 强化学习作为人工智能领域研究热点之一,它在游戏领域中的应用的研究进展与成果也引发了众多关注.为帮助研究与工程人员了 ...

  7. 137% YOLOv3加速、10倍搜索性能提升!百度飞桨推出模型压缩神器

    深度学习模型压缩,又有利器问世. 最新消息,历经一年四个版本打磨之后,百度推出最新深度学习模型压缩工具PaddleSlim1.0. 不仅囊括了深度学习模型压缩中常用的量化.剪裁.蒸馏.模型结构搜索.模 ...

  8. 分享丨强化学习是针对优化数据的监督学习?

    来源:AI科技大本营 作者 | Ben Eysenbach.Aviral Kumar.Abhishek Gupta  编译 | 凯隐 出品 | AI科技大本营(ID:rgznai100) 强化学习(R ...

  9. 137% YOLOv3加速、10倍搜索性能提升!这样的惊喜,最新版PaddleSlim有10个

    允中 发自 凹非寺  量子位 编辑 | 公众号 QbitAI 深度学习模型压缩,又有利器问世. 最新消息,历经一年四个版本打磨之后,百度推出最新深度学习模型压缩工具PaddleSlim1.0. 不仅囊 ...

最新文章

  1. tp点一共有多少_致命女人更新时间 致命女人第一季一共多少集在线观看地址
  2. 实战 PK!RTX2080Ti 对比 GTX1080Ti 的 CIFAR100 混合精度训练
  3. 济南电子机械工程学校计算机专业班主任,济南电子机械工程学校庆祝2020年教师节暨表彰大会隆重举行...
  4. t-sne 流形_流形学习[t-SNE,LLE,Isomap等]变得轻松
  5. cms的 php代码,KingCMS/PHP可执行代码
  6. 前端学习笔记之 创建节点 与 添加节点案例
  7. Linux用户登录自动拷贝文件,linux下ssh远程登录/scp远程复制文件/rsync远程同步命令的自动登录...
  8. 【后缀数组】bzoj2217 Secretary
  9. php上证指数抽奖代码,[高手指点] 美团网的抽奖是什么原理?
  10. 安装nvidia驱动和cuda工具包
  11. 遭遇灰鸽子BackDoor.Gpigeon.ymg新变种
  12. Onedrive 1T|5T 网盘获取
  13. python中 f代表什么_python 中下拉框中的f,v,m是什么意思??
  14. 信号电缆与计算机电缆区别,控制电缆与计算机电缆有什么区别
  15. 华为od机试79 (python)身高体重排序
  16. 大数据毕设/课设 - 水质情况实时监测预警可视化设计与实现
  17. 信息时代的管理信息系统
  18. ANSYS中vonnbsp;misesnbsp;stres…
  19. 手把手教你写Android项目文档,醍醐灌顶!
  20. ThinkSNS积分商城系统功能详解!

热门文章

  1. 数据分析:业务的分析指标
  2. ralink nvram API
  3. ffmpeg pts dts
  4. 设计界面的十二条简单的原则
  5. 冲刺上市却不被看好,绿茶餐厅为何不香了?
  6. Maya次世代武器全流程高模substance painter上材质贴图讲解
  7. 不小心删除了文件能恢复吗 误删除文件怎么找回
  8. [Buzz.Today]Tinkercad
  9. 如何批量制作扫描后即可在线阅读的二维码
  10. JavaScript学习手册三