5

J'ai un modèleHéritage Django: comment avoir une méthode pour toutes les sous-classes?

BaseModel 

et plusieurs sous-classes de celui-ci

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

en utilisant l'héritage multi-table. À l'avenir, je prévois d'avoir des dizaines de modèles de sous-classe.

Toutes les sous-classes ont une certaine mise en œuvre de la méthode

do_something() 

Comment puis-je appeler do_somthing d'une instance BaseModel?

Presque problème identique (sans solution) est affichée ici:
http://peterbraden.co.uk/article/django-inheritance

Une question simple: comment je résous BaseModel instnace à l'un de ses sous-classes instance sans vérifier toutes les sous-classes possibles?

Répondre

1

Travaillerez-vous avec une instance du type de base ou utiliserez-vous toujours des instances d'enfants? Si c'est le cas, appelez la méthode, même si vous avez une référence au type de base puisque l'objet lui-même est un type enfant.

Depuis la prise en charge de Python duck typing cela signifie que votre appel de méthode sera lié de manière appropriée puisque l'instance enfant aura vraiment cette méthode.

Un style de programmation pythonique qui détermine un type d'objet par inspection de sa méthode ou la signature attribut plutôt que par relation explicite à un objet de type (« Si il ressemble à un canard et caquette comme un canard, il doit être un canard. ") Par soulignant les interfaces plutôt que types spécifiques, le code bien conçu améliore sa flexibilité en permettant substitution polymorphique. Duck-typing évite les tests utilisant type() ou isinstance(). (Notez cependant que le typage de canard peut être complété avec classes de base abstraites.) Au lieu de cela, utilise typiquement des tests hasattr() ou programmation EAFP.

Notez que EAFP signifie Easier to Ask Forgiveness than Permission:

plus facile de demander pardon que la permission. Ce style de codage Python commun suppose l'existence de clés ou d'attributs valides et attrape des exceptions si l'hypothèse s'avère fausse. Ce style propre et rapide est caractérisé par la présence de nombreuses tentatives et sauf les déclarations. La technique contraste avec le style LBYL commun à de nombreux autres langages tels que C.

+1

Tout est correct, mais pas pertinent dans ce cas. Le problème est précisément que lorsqu'on travaille avec l'héritage multi-table de Django, on a souvent une instance de la classe de base disponible (ie interroger la table de base), même si l'objet est "vraiment" d'un type enfant (ie entrée dans une table enfant). –

0

Je suis d'accord avec Andrew. Sur certains sites, nous avons une classe qui supporte un tas de méthodes (mais pas de champs (c'était un refactor de pré-ORM)) qui sont communes à la plupart de nos classes de contenu. Ils utilisent hasattr pour contourner les situations où la méthode n'a pas de sens.

Cela signifie que la plupart de nos classes sont définies comme:

class Foo(models.Model, OurKitchenSinkClass): 

Fondamentalement, il est en quelque sorte d'un type de MixIn de chose. Fonctionne très bien, facile à entretenir.

2

Si vous voulez éviter de vérifier toutes les sous-classes possibles, la seule façon que je puisse envisager serait de stocker le nom de classe associé à la sous-classe dans un champ défini sur la classe de base. Votre classe de base peut avoir une méthode comme ceci:

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) 

Cette réponse ne me rend pas heureux et je trop aimé voir une meilleure solution, comme je confronté à un problème similaire bientôt.

+0

C'est essentiellement ce que vous avez à faire, mais il existe des façons plus simples de le faire (en utilisant contrib.contenttypes). Vois ma réponse. –

+0

Bonjour Carl, je ne vois pas votre réponse. Pourriez-vous republier peut-être, ou donner un lien utile. Merci –

+0

Peu importe, je l'ai eu. Merci Carl pour votre explication. –