2011-09-23 13 views
7

Il modello Discount descrive i campi comuni per tutti i tipi di sconti nel sistema. Ho alcuni modelli di proxy che descrivono algoritmi concreti per il totale della culcolazione. La classe Discount di base ha un campo membro denominato type, che è una stringa che identifica il suo tipo e la relativa classe.polimorfismo del modello django con ereditarietà del proxy

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 

Ma continuo a ricevere l'eccezione di AttributeError che dice che self non ha tipo. Come risolvere questo problema o esiste un altro modo per raggiungere questo obiettivo?

risposta

11

tuo metodo init ha bisogno di guardare in questo modo invece:

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

è necessario chiamare super __init__ prima sarà in grado di accedere a self.type.

Essere chiari con la chiamata del campo type dal type è anche una funzione integrata python, anche se non è possibile incontrare alcun problema.

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

+0

Grazie. Ancora una domanda, perché devo chiamare super __init__ prima di accedere alle proprietà degli oggetti? Ho pensato che fosse un python che rende tutti i membri dichiarati in oggetto accessibili nel costruttore, non in super classe (models.Model di Django). Come mai? – aambrozkiewicz

+2

Questo perché django.db.models.Model ha '__metaclass__ = ModelBase'. Ciò significa che django usa 'ModelBase' per creare la tua classe Model invece del normale' type'. Consiglio vivamente di leggere: http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python - e una volta che hai imparato le metaclassi, guarda il codice sorgente di django. –

0

chiamata super(Discount, self).__init__(*args, **kwargs) prima riferimento self.type.

Problemi correlati