Хитрая модель наследования - Джанго - PullRequest
14 голосов
/ 22 марта 2010

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

Итак, у меня 4 модели Person , Singer , Bassist и Ninja .

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


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

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

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


Помощь будет высоко ценится!

Ответы [ 4 ]

15 голосов
/ 22 марта 2010

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

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

class Person(models.Model):
    # ...
3 голосов
/ 22 марта 2010

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

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

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

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

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

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

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

2 голосов
/ 22 марта 2010

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

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

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

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

1 голос
/ 15 мая 2013

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

...