2011-09-23 10 views
7

私のDiscountモデルは、システム内のすべてのタイプの割引の共通フィールドを記述します。私は合計を計算するための具体的なアルゴリズムを記述するプロキシモデルをいくつか持っています。 Base 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の例外を受けて、self doesntは型を持っていると言っています。この問題を解決するにはどうすればいいですか、これを達成する別の方法がありますか?

答えて

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') 

あなたはself.typeにアクセスすることができます前に、スーパーの__init__を呼び出す必要があります。

typetypeは、問題に遭遇しないかもしれませんが、もpythonの組み込み関数です。

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

+0

ありがとうございます。もう1つの質問ですが、なぜオブジェクトプロパティにアクセスする前にsuper __init__を呼び出す必要がありますか?私はそれがオブジェクト内で宣言されたすべてのメンバーをスーパークラスではなくコンストラクタでアクセス可能にするPythonだと思っていました(models.Model from Django)。どうして? – aambrozkiewicz

+2

django.db.models.Modelに '__metaclass__ = ModelBase'があるためです。これは、djangoが 'ModelBase'を使って通常の' type'ではなくModelクラスを作成することを意味します。私は非常に読んで示唆しています:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python - そしてあなたがメタクラスをマスターしたら、djangoのソースコードを見てください。 –

0

コールsuper(Discount, self).__init__(*args, **kwargs)self.typeを参照する前に。