2011-09-23 20 views
7

Benim Discount model sisteminde indirimler her türlü ortak alanlar açıklanmaktadır. Kültürel toplam için somut algoritmayı tanımlayan bazı proxy modelleri var. Taban Discount10 sınıfının türünü ve ilgili sınıfını tanımlayan bir dize olan type adında bir üye alanı vardır.Django modeli polimorfizmi

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 

Ancak öznenin kendisinin türü olmadığını söyleyen AttributeError istisnası almaya devam ediyorum. Bunu nasıl düzeltebiliriz ya da bunu başarmanın başka bir yolu var mı?

cevap

11

Sizin init yöntemi artık şöyle bakmak gerekiyor:

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

Sen self.type erişmek mümkün olacak önce süper en __init__ çağırmanız gerekir.

type alan adınızı çağırarak, aynı zamanda python yerleşik bir işlev olduğundan, herhangi bir sorunla karşılaşmayabilirsiniz.

bakınız: self.type referans önce http://docs.python.org/library/functions.html#type

+0

Teşekkür ederiz. Bir soru daha, nesne özelliklerine erişmeden önce neden süper __init__ diye aramam gerekiyor? Ben tüm üyelerin süper sınıf değil (model.Model Django'dan) yapıcıda nesneye erişebileceğini bildiren bir python olduğunu düşündüm. Nasıl olur? – aambrozkiewicz

+2

Bunun nedeni, django.db.models.Model '__metaclass__ = ModelBase''e sahip olmasıdır. Bu, django'nun normal 'type' yerine Model sınıfınızı oluşturmak için' ModelBase' kullandığı anlamına gelir. Okumanızı şiddetle tavsiye ediyorum: http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python - ve bir kez metaclasslarda ustalaştıktan sonra django kaynak koduna bakın. –

0

çağrıyı super(Discount, self).__init__(*args, **kwargs).