2011-09-23 69 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之前。