Наследование сложной модели - Django

Я думаю, что это немного сложно, по крайней мере для меня.:)

Итак, у меня есть 4 модели Лицо, Певец, Басист и Ниндзя.

Певец, басист и ниндзя наследуют от Лица.


Проблема заключается в том, что каждый Человек может быть любым из его подклассов.

например. Человек может быть певцом и ниндзя. Другой человек может быть басистом и ниндзя. Другим может быть все три.

Как мне организовать мои модели?


Помощь будет очень признательна!

Ответы

Ответ 1

Множественное наследование плохо работает с базами данных (и ваши модели Django в конце концов должны сопоставляться с базой данных), а наследование часто является плохим способом моделирования "ролей" (поскольку роли людей меняются). Я бы использовал Singer, Bassist и Ninja как "роли", не как подклассы Person и подключил их через внешние ключи:

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

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

Ответ 2

В принципе вы можете сделать что-то вроде следующего:

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

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

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

Но тогда вы столкнулись с проблемой, что Person.roles.objects.all() может предоставить вам только экземпляры Role. Таким образом, вам нужен метод для приведения каждого экземпляра Role в подходящий подкласс, такой как Ninja или Pirate. Вот ссылка на поток, который обсуждает эту проблему.

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

Короче, Алекс и Стефано дали более полезные ответы, чем я.

Ответ 3

Я согласен с решением о ролях, как показано Алексом. У вас есть не разные подклассы людей. У вас есть разные роли, которые может иметь человек.

Но я слышу, как вы говорите: "Эй, ниндзя может иметь свойство" numberOfStars ", а певец может иметь свойство" highNote ". То же, что и для интерфейса: ниндзя может иметь метод throwStar() и исчезать(), в то время как певец может иметь sing() и getWasted(), а басист может иметь goFunky() и slapPop()

То, что у вас есть, - это случай, когда вашей модели данных нужна очень свободная схема. Настолько свободны, что на самом деле у вас нет схемы вообще. Если певец решает взять бас и импровизировать мелодию, это прекрасно. Если он хочет действовать как ниндзя, и вы вызываете throwStar, он вернет ошибку, потому что у него нет звезд, но вы могли бы в принципе назначить звезды певцу и заставить его бросать звезды.

То, чем вы занимаетесь, это мир онтологий, а не схемы. У вас есть ресурс, который является "чем-то", и это может быть какой-то тип, иметь некоторые свойства и т.д. Присутствие некоторых свойств может вывести тип, или наличие какого-либо типа может вывести другие типы. Вы не можете легко описать эту информацию с помощью простой модели данных django. Вам понадобится контекстно-зависимое хранилище графиков с индексом, такое как AllegroGraph, или реализуйте ваше взломанное решение с помощью rdflib.

Ответ 4

Вы можете сделать все свои профессии (Ninja, Bassist....) наследуемыми от Person в моделях, а затем использовать функцию isinstance в базовом коде, чтобы различают профессии Person.