2009-10-17 12 views
5

Ich habe ein ModellDjango Vererbung: wie eine Methode für alle Unterklassen zu haben?

BaseModel 

und mehrere Subklassen davon

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

Multi-Table Vererbung. In der Zukunft plane ich Dutzende von Unterklassenmodellen.

Alle Unterklassen haben einig Implementierung der Methode

do_something() 

Wie kann ich do_somthing aus einem Basemodel Beispiel nennen?

Nahezu identische Problem (ohne Lösung) wird hier gepostet:
http://peterbraden.co.uk/article/django-inheritance

Eine einfachere Frage: wie ich ohne zu prüfen, alle möglichen Subklassen Basemodel instnace zu einer ihrer Unterklassen-Instanz beheben?

Antwort

1

Werden Sie jemals mit einer Instanz des Basistyps arbeiten oder arbeiten Sie immer mit Instanzen der Kinder? Wenn letzteres der Fall ist, dann rufen Sie die Methode auf, auch wenn Sie einen Verweis auf den Basistyp haben, da das Objekt selbst IS-A Kindtyp ist.

Da Python duck typing unterstützt, bedeutet dies, dass Ihr Methodenaufruf ordnungsgemäß verknüpft wird, da die untergeordnete Instanz diese Methode wirklich verwenden wird.

A pythonic Programmierstil, die eines Objekts Art von Inspektion seiner Methode oder Attribut Unterschrift und nicht durch explizite Beziehung zu einem gewissen Typ Objekt bestimmt („Wenn es sieht aus wie eine Ente und quakt wie eine Ente, muss es eine Ente sein. ") Von Betonung Schnittstellen statt spezifischen Typen, gut gestaltete Code verbessert seine Flexibilität durch Erlauben polymorphe Substitution. Duck-Typisierung vermeidet Tests mit type() oder isinstance(). (Beachten Sie jedoch, dass Duck-Typisierung kann ergänzt werden mit abstrakten Basisklassen.) Stattdessen verwendet in der Regel hasattr() Tests oder EAFP-Programmierung.

Beachten Sie, dass EAFP für Easier to Ask Forgiveness than Permission steht:

Einfachere um Vergebung als Erlaubnis zu bitten. Dieser allgemeine Python-Codierungsstil geht von der Existenz gültiger Schlüssel oder Attribute aus und fängt Ausnahmen ab, wenn sich die Annahme als falsch herausstellt. Dieser saubere und schnelle Stil zeichnet sich durch das Vorhandensein vieler try und except Statements aus. Die Technik steht im Gegensatz zu dem LBYL-Stil, der vielen anderen Sprachen gemein ist, wie zum Beispiel C.

+1

Dies ist alles korrekt, aber in diesem Fall nicht relevant. Das Problem ist genau das, wenn man mit Django multi-table Vererbung arbeitet, hat man oft eine Instanz der Basisklasse verfügbar (dh von der Basistabelle abfragen), obwohl das Objekt "wirklich" eines Kindtyps ist (dh hat eine entsprechende Eintrag in einer Kindtabelle). –

0

Ich stimme Andrew zu. Auf einigen Websites haben wir eine Klasse, die eine ganze Reihe von Methoden unterstützt (aber keine Felder (dies war ein Vor-ORM-Refactor)), die den meisten, aber nicht allen unserer Inhaltsklassen gemeinsam sind. Sie nutzen hasattr, um Situationen zu umgehen, in denen die Methode keinen Sinn ergibt.

Das bedeutet, die meisten unserer Klassen sind definiert als:

class Foo(models.Model, OurKitchenSinkClass): 

Im Grunde ist es eine Art von MixIn Art der Sache. Funktioniert gut, einfach zu warten.

2

Wenn Sie vermeiden möchten, alle möglichen Unterklassen zu überprüfen, kann ich mir nur den Klassennamen merken, der der Unterklasse in einem Feld zugeordnet ist, das für die Basisklasse definiert ist. Ihre Basisklasse könnte ein Verfahren wie diese:

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) 

Diese Antwort macht mich nicht glücklich, und ich würde auch gerne eine bessere Lösung, um zu sehen, wie ich bald ein ähnliches Problem konfrontiert werden.

+0

Dies ist im Wesentlichen, was Sie tun müssen, aber es gibt sauberere Möglichkeiten, es zu tun (mit contrib.contenttypes). Siehe meine Antwort. –

+0

Hallo Carl, ich kann deine Antwort nicht sehen. Könnten Sie vielleicht einen neuen Beitrag schreiben oder einen nützlichen Link geben? Danke –

+0

Macht nichts, ich habe es. Danke Carl für deine Erklärung. –

Verwandte Themen