5

Ho un modelloEredità di Django: come avere un metodo per tutte le sottoclassi?

BaseModel 

e diverse sottoclassi di esso

ChildModelA(BaseModel), ChildModelB(BaseModel), ... 

utilizzando multi-tavolo eredità. In futuro prevedo di avere dozzine di modelli di sottoclassi.

Tutte le sottoclassi hanno qualche implementazione del metodo

do_something() 

Come posso chiamare do_somthing da un'istanza BaseModel?

problema

Quasi identico (senza soluzione) è pubblicato qui:
http://peterbraden.co.uk/article/django-inheritance

Una domanda semplice: come risolvo BaseModel instnace ad uno dei suoi un'istanza sottoclassi senza controllare tutte le possibili sottoclassi?

risposta

1

Lavorerai mai con un'istanza del tipo di base o lavorerai sempre con le istanze dei bambini? Se quest'ultimo è il caso, chiama il metodo, anche se hai un riferimento al tipo di base poiché l'oggetto stesso è un tipo di bambino IS-A.

Poiché il supporto Python duck typing significa che la chiamata al metodo sarà legata in modo appropriato poiché l'istanza figlio avrà veramente questo metodo.

uno stile di programmazione divinatorio che determina il tipo di un oggetto da ispezione del suo metodo o di un attributo firma piuttosto che esplicito relazione a qualche tipo di oggetto (“Se sembra un'anatra e fa qua qua come un anatra, deve essere un'anatra. ") Con enfatizzando le interfacce anziché i tipi specifici , il codice ben progettato migliora la sua flessibilità consentendo la sostituzione polimorfa . Duck-typing evita i test usando type() o isinstance(). (Si noti, tuttavia, che la digitazione degli anonimi può essere completata con le classi di base astratte ). Invece, lo impiega in genere test hasattr() o programmazione EAFP .

noti che EAFP sta per Easier to Ask Forgiveness than Permission:

più facile chiedere perdono che il permesso. Questo comune stile di codifica in Python presuppone l'esistenza di chiavi o attributi validi e rileva eccezioni se l'assunzione risulta falsa. Questo stile pulito e veloce è caratterizzato dalla presenza di molte dichiarazioni try e except. La tecnica contrasta con lo stile LBYL comune a molti altri linguaggi come C.

+1

Questo è tutto corretto, ma non rilevante in questo caso. Il problema è proprio il fatto che quando si lavora con l'ereditarietà multi-tavolo di Django, si ha spesso un'istanza della classe base disponibile (cioè da interrogare la tabella di base), anche se l'oggetto è "veramente" di un tipo figlio (cioè ha un corrispondente entrata in una tabella figlio). –

0

Sono d'accordo con Andrew. In un paio di siti abbiamo una classe che supporta molti metodi (ma non i campi (questo è stato il refactor pre-ORM) che sono comuni alla maggior parte delle nostre classi di contenuti. Fanno uso di hasattr per aggirare le situazioni in cui il metodo non ha senso.

Questo significa maggior parte delle nostre classi sono definite come:

class Foo(models.Model, OurKitchenSinkClass): 

Fondamentalmente si tratta di una specie di tipo MixIn di cose. Funziona alla grande, facile da mantenere.

2

Se si desidera evitare di controllare tutte le sottoclassi possibili, l'unico modo che posso pensare sarebbe quello di memorizzare il nome classe associato alla sottoclasse in un campo definito nella classe base. La classe di base potrebbe avere un metodo come questo:

def resolve(self): 
    module, cls_name = self.class_name.rsplit(".",1) 
    module = import_module(module) 
    cls = getattr(module, cls_name) 
    return cls.objects.get(pk=self.pk) 

Questa risposta non mi rendono felice e troppo mi piacerebbe vedere una soluzione migliore, come sarò di fronte a un problema simile al più presto.

+0

Questo è essenzialmente ciò che devi fare, ma ci sono modi più semplici per farlo (usando contrib.contenttypes). Vedi la mia risposta. –

+0

Ciao Carl, non sono in grado di vedere la tua risposta. Potresti ripubblicare forse, o dare un link utile. Grazie –

+0

Non importa, ho capito. Grazie Carl per la tua spiegazione. –

Problemi correlati