( Обновление : для Django 1.2 и новее, которые могут следовать запросам select_related по обратным отношениям OneToOneField (и, следовательно, к иерархиям наследования), существует более эффективный метод, который не требует добавления real_type
поле родительской модели. Доступно как InheritanceManager в проекте django-model-utils .)
Обычный способ сделать это - добавить ForeignKey к ContentType в родительской модели, которая хранит тип содержимого соответствующего «листового» класса. Без этого вам может потребоваться выполнить довольно много запросов к дочерним таблицам, чтобы найти экземпляр, в зависимости от размера вашего дерева наследования. Вот как я это сделал в одном проекте:
from django.contrib.contenttypes.models import ContentType
from django.db import models
class InheritanceCastModel(models.Model):
"""
An abstract base class that provides a ``real_type`` FK to ContentType.
For use in trees of inherited models, to be able to downcast
parent instances to their child types.
"""
real_type = models.ForeignKey(ContentType, editable=False)
def save(self, *args, **kwargs):
if not self._state.adding:
self.real_type = self._get_real_type()
super(InheritanceCastModel, self).save(*args, **kwargs)
def _get_real_type(self):
return ContentType.objects.get_for_model(type(self))
def cast(self):
return self.real_type.get_object_for_this_type(pk=self.pk)
class Meta:
abstract = True
Это реализовано как абстрактный базовый класс, чтобы сделать его многократно используемым; вы также можете поместить эти методы и FK непосредственно в родительский класс в вашей конкретной иерархии наследования.
Это решение не будет работать, если вы не сможете изменить родительскую модель. В этом случае вы в значительной степени застряли, проверяя все подклассы вручную.