如何在Django的Transaction模型中保存订单财务计算结果?
Django店铺管理应用:计算并保存订单关联产品的利润、收入和成本到Transaction模型
项目背景
使用Django 4.2.3开发用于作品集的小型店铺管理应用,临时采用SQLite数据库。项目包含4个模型,其中Transaction模型需要存储关联订单的产品总利润、总收入和总成本。尝试重写Transaction的save方法调用计算方法,但未成功。项目欢迎帮助或协作,会给予适当署名。
现有代码
Transaction模型(finance应用)
from django.db import models from core.models import Order class Transaction(models.Model): date = models.DateTimeField("Transaction's date", auto_now=True) order = models.ForeignKey(Order, on_delete=models.CASCADE) total_profit = models.IntegerField("Transaction's Profit", default=0) total_cost = models.IntegerField("Transaction's Income", default=0) total_income = models.IntegerField("Transaction's Income", default=0) def __str__(self): return f"Transaction #{self.pk}" # 问题所在:不知道如何保存计算结果 def calc_cost(self): for product in self.order.product.objects.all(): self.total_cost += product.price_cost() def calc_income(self): for product in self.order.product.objects.all(): self.total_income += product.price_sell() def calc_profit(self): self.total_profit = self.total_income - self.total_cost
Product和Order模型(core应用)
class Product(models.Model): name = models.CharField("Product Name", default="Product", max_length=200) price_sell = models.IntegerField("Product sell Price", default=0) price_cost = models.IntegerField("Product cost Price", default=0) stock = models.IntegerField("Product Stock", default=0) description = models.TextField("Product Description", default="", max_length=300) image = models.ImageField("Product Image", default=None) def __str__(self): return f"{self.name}" class Order(models.Model): ordered_by = models.CharField("Person who ordered", max_length=100, default="---") created_datetime = models.DateTimeField("Created datetime", auto_now_add=True) updated_datetime = models.DateTimeField("Updated datetime", auto_now=True) completed = models.BooleanField("Order Status", default=False) product = models.ForeignKey( Product, on_delete=models.CASCADE, ) def __str__(self): return f"{self.product}"
问题分析与解决方案
核心问题
- 未触发计算逻辑:没有重写
save方法,导致计算方法从未被调用。 - Order模型设计缺陷:
product字段为ForeignKey,仅支持单个产品关联,不符合多产品订单的实际场景。 - 语法错误:
self.order.product.objects.all()错误:product是ForeignKey对应单个对象,不是查询集,无法调用objects.all()。product.price_cost()/product.price_sell()错误:这两个是模型字段,不是方法,无需加括号调用。
- 字段命名错误:
total_cost的verbose_name与total_income重复,易混淆。
修正后的代码
第一步:优化Order模型(支持多产品订单)
添加OrderItem中间模型,记录订单中每个产品的购买数量:
# core/models.py from django.db import models class Product(models.Model): name = models.CharField("产品名称", default="产品", max_length=200) price_sell = models.IntegerField("售价", default=0) price_cost = models.IntegerField("成本价", default=0) stock = models.IntegerField("库存", default=0) description = models.TextField("产品描述", default="", max_length=300) image = models.ImageField("产品图片", default=None) def __str__(self): return f"{self.name}" class OrderItem(models.Model): order = models.ForeignKey("Order", on_delete=models.CASCADE, related_name="items") product = models.ForeignKey(Product, on_delete=models.CASCADE) quantity = models.IntegerField("数量", default=1) def __str__(self): return f"{self.quantity} x {self.product.name}" class Order(models.Model): ordered_by = models.CharField("下单人", max_length=100, default="---") created_datetime = models.DateTimeField("创建时间", auto_now_add=True) updated_datetime = models.DateTimeField("更新时间", auto_now=True) completed = models.BooleanField("订单状态", default=False) def __str__(self): return f"订单 #{self.pk}"
第二步:修正Transaction模型的计算与保存逻辑
# finance/models.py from django.db import models from core.models import Order class Transaction(models.Model): date = models.DateTimeField("交易日期", auto_now=True) order = models.ForeignKey(Order, on_delete=models.CASCADE) total_profit = models.IntegerField("总利润", default=0) total_cost = models.IntegerField("总成本", default=0) total_income = models.IntegerField("总收入", default=0) def __str__(self): return f"交易 #{self.pk}" def calc_cost(self): # 重置为0,避免多次保存时累加错误 self.total_cost = 0 for item in self.order.items.all(): self.total_cost += item.product.price_cost * item.quantity def calc_income(self): self.total_income = 0 for item in self.order.items.all(): self.total_income += item.product.price_sell * item.quantity def calc_profit(self): self.total_profit = self.total_income - self.total_cost def save(self, *args, **kwargs): # 保存前执行所有计算 self.calc_cost() self.calc_income() self.calc_profit() # 调用父类方法完成最终保存 super().save(*args, **kwargs)
关键说明
- 自动触发计算:重写
save方法,每次保存Transaction时自动执行计算,确保数据同步。 - 避免累加错误:计算前重置
total_cost和total_income为0,防止多次保存导致数值异常。 - 多产品支持:通过
OrderItem模型实现一个订单对应多个产品,同时记录数量,计算更贴合实际。 - 字段规范:修正verbose_name重复问题,统一使用中文命名提升可读性。
内容的提问来源于stack exchange,提问作者Technopy
相关产品推荐
相关产品推荐

