2010-03-22 6 views
14

Je pense que c'est un peu difficile, au moins pour moi. :)Héritage du modèle Tricky - Django

J'ai donc 4 modèles personne, Chanteur, Bassiste et Ninja. Chanteur, Bassiste et Ninja héritent de la personne.


Le problème est que chaque personne peut être l'une de ses sous-classes.

par exemple. Une personne peut être un chanteur et un ninja. Une autre personne peut être un bassiste et un ninja. Un autre peut être tous les trois.

Comment dois-je organiser mes modèles?


Aide serait grandement appréciée!

+4

Qu'en est-il des pirates? : P –

+4

Sur quel type de projet travaillez-vous? Cela semble génial! Je veux être un bassiste-ninja chaotique/maléfique. –

+3

Une fois j'ai eu un ami jouant un barde. Il est mort, son cœur a été remplacé et est devenu diabolique (ne demandez pas). De retour à la vie, il jeta le luth et prit une guitare électrique (encore une fois, ne le demandez pas) et inspira le courage en choisissant les cordes avec son couteau tout en faisant grogner le métal. Clairement, c'était génial. –

Répondre

15

L'héritage multiple ne fonctionne pas bien avec les bases de données (et vos modèles Django doivent être mappés à une base de données), et l'héritage est souvent un mauvais moyen de modéliser les "rôles" (car les rôles des utilisateurs changent) . J'aurais chanteur, bassiste et Ninja comme « rôles », pas comme sous-classes de personne, et de les connecter via les clés étrangères:

class Singer(models.Model): 
    person = models.ForeignKey('Person') 
    # ... 

class Person(models.Model): 
    # ... 
+0

@Alex: au lieu des rôles ensemble à travers l'héritage multiple, y aurait-il une autre façon de les fusionner? Je ne me sens pas à l'aise d'utiliser des FK pour associer les rôles à la classe Person, car l'information de la personne dépend entièrement de qui ils sont. Je devrais peut-être réfléchir davantage, merci beaucoup Alex !! – RadiantHex

+0

C'est la voie à suivre, à moins que "chanteur" ne soit rien de plus qu'un descripteur .... dans ce cas, ajouter simplement 'is_singer = models.BooleanField()' au modèle 'Person' fera un modèle simplifié et requêtes plus rapides –

+0

ce sont des rôles, pas des sous-classes. Les sous-classes dans les taxonomies _single inheritance_ basées sur les classes traditionnelles s'excluent mutuellement. Par exemple, Chien, Chat et Lapin peuvent tous hériter de Mammifères, mais il n'y a pas d'animal qui soit à la fois Chien * et * Lapin. Les langages qui supportent l'héritage multiple sont plus tolérants à propos de ces choses, mais dans ce cas je suis d'accord avec Alex que l'utilisation de l'héritage serait une erreur de modélisation, même si cela fonctionnait facilement. –

2

Je suis d'accord sur la solution des rôles, comme décrit par Alex. Ce que vous avez n'est pas différentes sous-classes de personnes. Vous avez différents rôles qu'une personne peut avoir. Mais je vous entends dire: "hé, le ninja peut avoir une propriété" numberOfStars ", alors qu'un chanteur peut avoir une propriété" highestNote "Identique à l'interface: un ninja peut avoir la méthode throwStar() et disparaître(), alors qu'un chanteur peut avoir chanté() et getWasted(), et le bassiste peut avoir goFunky() et slapPop()

Ce que vous avez ici est un cas où votre modèle de données nécessite un schéma très lâche Si le chanteur décide de prendre la basse et d'improviser un morceau, ça va ... S'il veut jouer le rôle de ninja, et que vous appelez throwStar, il va retourner une erreur , parce qu'il n'a pas d'étoiles, mais vous pourriez en principe assigner des étoiles à un chanteur et lui faire jeter des étoiles

Dans ce que vous vous aventurez dans le monde des ontologies, plutôt que des schémas. Vous avez une ressource, qui est "quelque chose" et ce quelque chose peut être un type, avoir des propriétés, etc. La présence de certaines propriétés peut inférer le type, ou la présence de certains types peut inférer d'autres types. Vous ne pouvez pas décrire facilement cette information avec le simple modèle de données django. Ce dont vous avez besoin, c'est d'un magasin de graphes inférenciés, sensibles au contexte, comme AllegroGraph, ou implémentez votre solution piratée en utilisant rdflib.

+2

Vous mélangez plusieurs problèmes ici. Les chanteurs et les ninjas peuvent exiger des attributs différents, mais cela ne signifie en aucun cas que vous avez soudainement un schéma dynamique complètement ouvert. La façon simple et évidente de représenter une connaissance propre à un type de personne est d'avoir une table de chanteur qui contient des faits sur les chanteurs, une table de ninja correspondante, et ainsi de suite, en plus de la table des personnes. Toutes les tables auraient un PK de person_id, avec des FK selon le cas. –

3

En principe, vous pouvez faire quelque chose comme ce qui suit:

class Role(models.Model):  
    ...... 

class Ninja(Role): 
    ....... 

class Person(models.Model): 
     roles = models.ManyToManyField(Role) 

Mais vous courez pour le problème que Person.roles.objects.all() ne peut vous donner des exemples de rôle. Vous avez donc besoin d'une méthode pour lancer chaque instance de Role dans une sous-classe appropriée comme Ninja ou Pirate. Voici un lien vers un thread qui traite de ce problème.

http://groups.google.com/group/django-users/browse_thread/thread/f4241bc16455f92d/7268c3f7bca6b046

Donc en bref Alex et Stefano ont donné des réponses plus utiles que moi.

1

Vous pouvez faire toutes vos professions (Ninja, le contrebassiste ....) hériter de Personne dans les modèles, puis utilisez la fonction isinstance dans le code back-end pour distinguer entre les professions d'une personne .

Questions connexes