You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中如何为Product模型关联不同数量Supply物料实现手工项目成本核算

模型设计方案

核心实现思路

你需要的是带额外属性的多对多关系,Django提供了through参数用于定义多对多的中间关联模型,正好可以存储你需要的「物料用量、计量单位」这类额外信息,完全不需要硬编码多个外键字段。


代码实现

第一步:新增中间关联模型+计量单位枚举

from django.db import models
from django.utils.translation import gettext_lazy as _

# 计量单位枚举,若后续需要扩展可单独拆为模型
class UnitChoices(models.TextChoices):
    CUBIC_INCH = 'cubic_inch', _('立方英寸')
    SQUARE_INCH = 'square_inch', _('平方英寸')
    EACH = 'each', _('个/件')

# 产品-物料中间关联表,存储单种物料的用量信息
class ProductSupply(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='supply_uses')
    supply = models.ForeignKey(Supply, on_delete=models.CASCADE)
    usage_amount = models.FloatField(verbose_name='用量')
    usage_unit = models.CharField(max_length=20, choices=UnitChoices.choices, verbose_name='计量单位')

    # 自动计算当前物料的成本
    @property
    def item_cost(self):
        try:
            if self.usage_unit == UnitChoices.CUBIC_INCH:
                return round(self.usage_amount * self.supply.cost_per_cubic_inch, 2)
            elif self.usage_unit == UnitChoices.SQUARE_INCH:
                return round(self.usage_amount * self.supply.cost_per_square_inch, 2)
            elif self.usage_unit == UnitChoices.EACH:
                return round(self.usage_amount * self.supply.cost_per_each, 2)
        except:
            return "N/A"
    
    def __str__(self):
        return f"{self.product.name} - {self.supply.name}: {self.usage_amount}{self.get_usage_unit_display()}"

第二步:修改原有Product模型

class Product(models.Model):
    name = models.CharField(max_length = 200, null = True, blank = True)
    product_type = models.ForeignKey(ProductType, null = True, blank = True, on_delete = models.CASCADE)
    # 新增多对多关联,通过中间表ProductSupply实现动态绑定任意数量物料
    supplies = models.ManyToManyField(Supply, through=ProductSupply, blank=True)

    # 自动计算该产品所有物料的总成本
    @property
    def total_material_cost(self):
        total = 0
        for supply_use in self.supply_uses.all():
            cost = supply_use.item_cost
            if cost != "N/A":
                total += cost
        return round(total, 2) if total else "N/A"

    def __str__(self):
        return self.name

使用说明

  • 一个Product可以绑定任意数量的Supply,不需要提前预留字段
  • 录入物料时只需选择对应Supply、填写用量、选择计量单位,系统会自动计算单种物料成本、产品总物料成本
  • 如果在Django Admin中使用,可以配置Inline实现在Product编辑页直接增删改关联物料:
from django.contrib import admin
from .models import Product, ProductSupply

class ProductSupplyInline(admin.TabularInline):
    model = ProductSupply
    extra = 1 # 默认显示1条空记录,可手动添加更多

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = [ProductSupplyInline]

内容的提问来源于stack exchange,提问作者Tony Dean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 16:27:00