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

Django中如何让Product实例的price字段动态返回折扣价?

实现方案

方案一:使用@property装饰器(推荐)

直接在Product模型中添加@property装饰的price方法,覆盖原有字段的访问逻辑,调用product.price时会自动根据is_discount返回对应值:

# models.py
from django.db import models

class Product(models.Model):
    price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, default=0.00)
    discount = models.DecimalField(max_digits=10, decimal_places=2, blank=True, default=0.00)
    is_discount = models.BooleanField(default=False)

    @property
    def price(self):
        # 直接获取原始price字段值,避免递归调用
        original_price = object.__getattribute__(self, 'price')
        return self.discount if self.is_discount else original_price

优点:

  • 写法简洁直观,符合Python属性访问习惯
  • 无需修改现有数据库字段,不影响已有数据
  • 视图中无需额外判断,直接调用product.price即可

优化版(适合新开发项目)

如果允许调整字段命名,可将字段名改为更清晰的命名,避免混淆:

class Product(models.Model):
    regular_price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, default=0.00)
    discount_price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, default=0.00)
    use_discount = models.BooleanField(default=False)

    @property
    def price(self):
        return self.discount_price if self.use_discount else self.regular_price

方案二:重写__getattribute__方法

通过重写模型的__getattribute__方法拦截属性访问,完全保留原有字段名:

# models.py
from django.db import models

class Product(models.Model):
    price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, default=0.00)
    discount = models.DecimalField(max_digits=10, decimal_places=2, blank=True, default=0.00)
    is_discount = models.BooleanField(default=False)

    def __getattribute__(self, name):
        if name == 'price':
            # 获取is_discount的值,避免递归调用
            is_discount = object.__getattribute__(self, 'is_discount')
            if is_discount:
                return object.__getattribute__(self, 'discount')
        return object.__getattribute__(self, name)

优点:

  • 完全保留原有字段名,视图调用逻辑不变

缺点:

  • __getattribute__会拦截所有属性访问,逻辑复杂时易出问题,调试难度高
  • 必须使用object.__getattribute__获取原始属性值,避免递归调用

视图调用示例

无论采用哪种方案,视图中都可以直接调用product.price获取对应价格:

# views.py
def page(request):
    product = Product.objects.get(pk=1)
    current_price = product.price  # 自动返回折扣价或原价

内容的提问来源于stack exchange,提问作者Vitalii Lastname

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:25:15