Вы хотите Абстрактный базовый класс («виртуальный» ничего не значит в Python.)
Из документации:
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
Редактировать
"В OO-программировании при вызове object.method () вы должны получить реализацию самого низкого подкласса."
True. Но не вся история.
Это не проблема ОО. Или даже проблема с Python или Django. Это проблема ORM.
Вопрос: «Какой объект реконструируется в конце ссылки FK?» И ответ заключается в том, что нет стандартного, очевидного ответа о том, как обрабатывать преобразование значения FK в объект.
У меня есть строка в AnimalHome
со значением animals
, равным 42. Это относится к Animal.objects.get(pk=42)
. Какой подкласс Animal? Кошка? Собака? Как слой ORM узнает, должен ли он делать Dog.objects.get(pk=42)
или Cat.objects.get(pk=42)
?
«Но подожди», - говорите вы. «Он должен получить объект Animal, а не объект Dog или Cat». Вы можете на это надеяться, но это не то, как работает Django ORM. Каждый класс представляет собой отдельную таблицу. Cat и Dog - по определению - отдельные таблицы, с отдельными запросами. Вы не используете хранилище объектов. Вы используете ORM для реляционных таблиц.
Редактировать
Во-первых, ваш запрос работает, только если Dog и Cat используют общий генератор ключей и не имеют перекрывающихся наборов PK.
Если у вас есть собака с PK 42 и кошка с PK 42, у вас есть проблема. А поскольку вы не можете легко управлять генерацией ключей, ваше решение не может работать.
Ошибка идентификации типа во время выполнения. Это не объектно-ориентированное во многих отношениях. Почти все, что вы можете сделать, чтобы избежать RTTI, лучше, чем постоянно расширяющаяся последовательность операторов if для различения подклассов.
Однако модель, которую вы пытаетесь построить, является, в частности, патологической проблемой для систем ORM. На самом деле, настолько патологический, что я почти готов поспорить, что это домашнее задание. [Также существуют патологические проблемы для систем на чистом SQL. Они часто появляются как домашнее задание.]
Проблема в том, что ORM не может делать то, что, как вы думаете, он должен делать. Итак, у вас есть два варианта.
- Прекратить использование Django.
- Делай то, что Джанго делает напрямую.
- Нарушить руководящие принципы проектирования ОО и прибегнуть к таким хрупким вещам, как RTTI, что делает чрезвычайно сложным добавление еще одного подкласса животных.
Рассмотрите этот способ сделать RTTI - он включает в себя как имя класса, так и PK
KIND_CHOICES = (
( "DOG", "Dog" ),
( "CAT", "Cat" ),
)
class Animal( models.Model ):
kind = models.CharField( max_length= 1, choices=KIND_CHOICES )
fk = models.IntegerField()
def get_kind( self ):
if kind == "DOG":
return Dog.objects.get( pk = fk )
elif kind == "CAT":
return Cat.objects.get( pk = fk )