2009-05-14 7 views
2

Quand j'ai une classe de modèle django donné comme ceci: par exempleComment obtenir un objet sous-classé d'un modèle de django

class SomeClass(BaseClass): 
    other_field = models.CharField(max_length = 80) 

class BaseClass(models.Model): 
    some_field = models.CharField(max_length = 80) 
    ... 

et certaines sous-classes de celui-ci,

Je sais que je peut obtenir l'objet dérivé en appelant

base = BaseClass.objects.get(pk=3) 
my_obj= base.someclass 

maintenant, le problème se pose que j'ai plusieurs sous-classes, et tout ce que j'ai est un n instance de la classe de base. Comment puis-je accéder à l'objet sous-classé sans le savoir à l'avance?


L'idée est de charger une vue correspondante et de faire cela. Les fonctionnalités de mon projet n'ont qu'un nombre limité d'actions par défaut pour ces modèles, comme la vue, l'édition, la suppression, etc. Ce que je ne veux pas, c'est exposer le type de l'objet donné via URL.

Répondre

3

Il n'y a pas de manière intégrée.

Peut-être que la meilleure chose à faire est de définir un champ derived_type sur votre classe de base, qui est défini automatiquement lors de la sauvegarde de la classe dérivée. Vous pouvez alors avoir une méthode get_derived sur la base qui vérifie la valeur de derived_type et renvoie l'objet dérivé réel.

+0

Voilà comment je l'ai manipulé dans le Attention, le champ derived_type ne doit être défini que lors de la sauvegarde initiale (lorsque vous savez que vous enregistrez le sous-type), et ne sera jamais modifié par la suite.Sinon, il est facile de charger l'instance en tant qu'instance de BaseClass, enregistrer - et votre champ derived_type pense maintenant qu'il s'agit d'une BaseClass. –

+0

De nos jours, il y a une manière intégrée, regardez ma réponse .... –

2

Comment puis-je accéder à l'objet sous-classé sans le savoir à l'avance?

Pourquoi cela serait-il utile? Si vous ne savez pas quelle classe vous voulez, vous ne saurez pas non plus quelles méthodes appeler ou quels attributs peuvent être inspectés.


L'idée est de charger une vue correspondante et laisser que faire les choses. Les fonctionnalités de mon projet n'ont qu'un nombre limité d'actions par défaut pour ces modèles, comme la vue, l'édition, la suppression, etc. Ce que je ne veux pas, c'est exposer le type de l'objet donné via URL.

Si vous savez à l'avance sous-classe l'ensemble du modèle, ou sont prêts à les inscrire à une liste de vue centrale, vous pouvez faire quelque chose comme ceci:

VIEWS = [('subclass_a', a_views), ('subclass_b', b_views)] 

def edit(request): 
    base = (get base somehow) 

    for attrname, views in VIEWS: 
     if getattr(base, attrname) is not None: 
      return views['edit'] 

Selon combien de types différents de vos vues, vous pouvez extraire la recherche dans une fonction distincte, de sorte que la vue de fin est quelque chose comme:

def edit(request): 
    return generic_base_view(request, 'edit') 
+0

Heh .. Presque pensé que cela viendrait. L'idée est de charger une vue correspondante et de laisser faire cela. Les fonctionnalités de mon projet n'ont qu'un nombre limité d'actions par défaut pour ces modèles, comme la vue, l'édition, la suppression, etc. Ce que je ne veux pas, c'est exposer le type de l'objet donné via URL. –

+0

Ajout de votre réponse à la question, afin que les autres puissent la voir plus facilement. –

+0

Merci pour l'idée .. malheureusement, cela compliquerait trop la conception de l'application :( –

2

Pour les personnes qui cherchent dans cette réponse un peu plus tard que la question a été publiée et la réponse acceptée a été donnée, dans les versions les plus récentes de django, cela est possible plus directement, voir: django documentation about multi table inheritance

regard sur l'exemple des lieux et des restaurants. L'objet de base est un lieu, et la sous-classe est un restaurant. Vous pouvez obtenir la sous-classe par place.restaurant qui donne une exception, vous pouvez attraper si l'endroit n'est pas un restaurant. J'ajoute ceci parce que la réponse acceptée pourrait être un peu désuète et m'a conduit à la mauvaise piste.

Questions connexes