Django模型的代理继承多态性

8 投票
2 回答
2503 浏览
提问于 2025-04-17 02:54

我的 Discount 模型描述了系统中所有类型折扣的共同字段。我有一些代理模型,它们描述了计算总额的具体算法。基础的 Discount 类有一个成员字段,叫做 type,它是一个字符串,用来标识折扣的类型和相关的类。

class Discount(models.Model):
  TYPE_CHOICES = (
    ('V', 'Value'),
    ('P', 'Percentage'),
  )

  name = models.CharField(max_length=32)
  code = models.CharField(max_length=32)
  quantity = models.PositiveIntegerField()
  value = models.DecimalField(max_digits=4, decimal_places=2)
  type = models.CharField(max_length=1, choices=TYPE_CHOICES)

  def __unicode__(self):
    return self.name

  def __init__(self, *args, **kwargs):
    if self.type:
      self.__class__ = getattr(sys.modules[__name__], self.type + 'Discount')
    super(Discount, self).__init__(*args, **kwargs)

class ValueDiscount(Discount):
  class Meta:
    proxy = True

  def total(self, total):
    return total - self.value

但是我总是遇到一个叫做 AttributeError 的错误,提示说 self 没有 type 这个属性。我该怎么解决这个问题,或者有没有其他方法可以实现这个功能?

2 个回答

1

在使用 self.type 之前,先调用 super(Discount, self).__init__(*args, **kwargs)

13

你的初始化方法应该像这样:

def __init__(self, *args, **kwargs):
    super(Discount, self).__init__(*args, **kwargs)
    if self.type:
        self.__class__ = getattr(sys.modules[__name__], self.type + 'Discount')

在你能访问到 self.type 之前,必须先调用父类的 __init__ 方法。

要注意不要把你的字段命名为 type,因为 type 也是 Python 的一个内置函数,虽然你可能不会遇到什么问题。

详情请见: http://docs.python.org/library/functions.html#type

撰写回答