( Aktualizacja : dla Django 1.2 i nowszych, które mogą podążać za zapytaniami select_related w odwrotnych relacjach OneToOneField (a tym samym w dół hierarchii dziedziczenia), dostępna jest lepsza technika, która nie wymaga dodanego real_type
pola w modelu nadrzędnym. Jest dostępna jako InheritanceManager w projekt django-model-utils .)
Zwykłym sposobem jest dodanie ForeignKey do ContentType w modelu Parent, który przechowuje typ zawartości odpowiedniej klasy „leaf”. Bez tego może być konieczne wykonanie wielu zapytań w tabelach potomnych, aby znaleźć instancję, w zależności od tego, jak duże jest twoje drzewo dziedziczenia. Oto, jak zrobiłem to w jednym projekcie:
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
Jest to zaimplementowane jako abstrakcyjna klasa bazowa, aby umożliwić wielokrotne użycie; możesz również umieścić te metody i FK bezpośrednio w klasie nadrzędnej w określonej hierarchii dziedziczenia.
To rozwiązanie nie zadziała, jeśli nie możesz zmodyfikować modelu nadrzędnego. W takim przypadku utkniesz, sprawdzając ręcznie wszystkie podklasy.