2013-05-01 3 views
4

В настоящее время я работаю над моделью в Django, в которой задействована одна модель, которая может иметь множество различных черт в зависимости от того, какой объект она есть. Итак, допустим, у нас есть модель под названием Mammal, которая может быть слоном или дельфином (с их собственными чертами «tusk_length» и «flipper_length» соответственно).Django - Полиморфные модели или одна большая модель?

Основные принципы ООП кричат ​​«полиморфизм», и я склонен согласиться. Но, поскольку я новичок в Django, я сначала хочу знать, является ли это лучшим способом сделать это в Django. Я слышал много примеров и некоторых людей, дающих свои предпочтения в отношении сингулярных гигантских моделей.

Я уже пробовал использовать GenericForeignKeys, как описано здесь: How can I restrict Django's GenericForeignKey to a list of models?. Хотя это решение работает красиво, мне не нравится неспособность фильтровать и что отношения - это только один способ. То есть, пока вы можете получить Дельфин из объекта Mammal, вы не можете получить объект Mammal из дельфина.

И так, вот мои два варианта:

Выбор A:

from django.db import models 
class Mammal(models.Model): 
    hair_length = models.IntegerField() 
    tusk_length = models.IntegerField() 
    flipper_length = models.IntegerField() 
    animal_type = models.CharField(max_length = 15, choices = ["Elephant", "Dolphin"] 

Вариант B:

from django.db import models 
class Mammal(models.Model): 
    hair_length = models.IntegerField() 

class Elephant(Mammal): 
    tusk_length = models.IntegerField() 

class Dolphin(Mammal): 
    flipper_length = models.IntegerField() 

Выбор B, от того, что я понимаю, имеет преимущество лучше код при запросе и перечислении всех слонов или дельфинов. Тем не менее, я заметил, что не так просто собрать всех слонов из списка млекопитающих (есть ли запрос для этого?), Не помещая в класс класс animal_type, причем по умолчанию он зависит от класса.

Это приводит к другой проблеме, которую я вижу с полиморфизмом, который не будет показан в этом примере выше или в моем приложении, но стоит упомянуть, что было бы трудно редактировать объект Дельфина в слон без удаления Дельфина полностью.

В целом, существует ли какое-либо общее предпочтение или какая-либо большая причина, по которой я не должен использовать полиморфизм?

ответ

3

Моя рекомендация, в целом с базой данных, заключается в том, чтобы избежать наследования. Это усложняет доступ и обновления.

В Django попробуйте использовать абстрактный класс для базовой модели. Это означает, что для него не будет создана таблица db. Его поля/столбцы будут автоматически созданы в дочерних моделях. Преимущество: повторное использование кода в коде Django/Python и простой, плоский дизайн в базе данных. Штраф: это больше работы для управления/запроса смешанной коллекции детских моделей.

Смотрите пример здесь: Django Patterns: Model Inheritance

В качестве альтернативы, вы можете изменить понятие «Млекопитающие» до «MammalTraits.» И включите объект MammalTraits внутри каждого определенного класса млекопитающих. В коде это композиция (has-a). В db это будет выражаться как внешний ключ.

+0

Теперь основная проблема, которую я вижу с использованием абстрактного класса (в моем случае, а не вообще), - это уже существующая и заполненная таблица млекопитающих. Изменение его на «MammalTraits» могло бы работать, но я хочу обеспечить взаимную связь между одним MammalTrait и одним из объектов Dolphin/Elephant. Это, конечно, просто в теории, но мне нужно было бы обеспечить наличие только одного дельфина или одного слона, который, я полагаю, не слишком сложный (переписывая метод save() для проверки?). – limasxgoesto0

+0

Hm. Однако я вижу вашу точку зрения на несколько дочерних моделей. Фильтрация всех млекопитающих дельфином была бы немного хлопот ... – limasxgoesto0

+1

Пересмотрено это - и я на самом деле закончил использование абстрактного класса в качестве базовой модели для чего-то нового, что я делал. Поэтому вывод для меня заключается в использовании одной из двух вещей, которые вы предлагаете здесь для новой модели, но если это существующая модель, которая должна стать полиморфной с существующими данными в реальном времени, может быть безопаснее просто насытить ее всеми полями, которые вы необходимость. – limasxgoesto0

1

Мы закончили тем, что столкнулись с большим столом с множеством обычно пустых столбцов. Наши рассуждения состояли в том, что (в данном случае) наша таблица Млекопитающих - это все, о чем мы будем спрашивать, и не было (интуитивного) способа отфильтровать определенные типы Млекопитающих, кроме того, чтобы вручную проверить, имели ли они «дельфина» или «слона» «объект, который затем выбросил ошибку, если они этого не сделали. Даже поиск типа объекта, возвращенного из запроса, который определенно был слоном, все еще возвращал «Млекопитающее». Было бы трудно распространять любые обходные пути Pythonic для написания чистого SQL, который регулярно решает один из наших данных.

+0

AFAIK Ваше решение называется «однонаправленным наложением таблицы». – guettli

Смежные вопросы