2011-09-23 34 views
7

我的Discount模型描述了系统中所有类型折扣的通用字段。我有一些代理模型,它们描述了整个计算的具体算法。基类Discount类具有名为type的成员字段,该字段是标识其类型及其相关类的字符串。带代理继承的django模型多态性

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的异常,说自己没有类型。如何解决这个问题,或者有另一种方法来实现这一目标?

回答

11

你的init方法需要这个样子,而不是:

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

你需要调用超类的__init__,你将能够访问self.type之前。

与调用您的字段type Becareful因为type也是一个python内置函数,但您可能不会遇到任何问题。

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

+0

谢谢。还有一个问题,为什么我需要在访问对象属性之前调用super __init__?我认为这是一个python,它使所有成员在构造函数中声明对象可访问,而不是超类(来自Django的models.Model)。怎么来的? – aambrozkiewicz

+2

这是因为django.db.models.Model有'__metaclass__ = ModelBase'。这意味着django使用'ModelBase'来创建你的Model类而不是常规的'type'。我强烈建议阅读:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python - 一旦你掌握了元类,看看django的源代码。 –

0

呼叫super(Discount, self).__init__(*args, **kwargs)引用self.type之前。