( Оновлення : Для 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 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 безпосередньо на батьківському класі у вашій ієрархії успадкування.
Це рішення не буде працювати, якщо ви не можете змінити батьківську модель. У цьому випадку ви майже застрягли перевіряти всі підкласи вручну.