У меня есть схема наследования с несколькими таблицами, похожая на следующую:
class NodeData(models.Model):
node = models.ForeignKey(Node, db_index = True)
value = models.FloatField(default = 0)
name = models.TextField(unique=True, blank=True)
class Node(models.Model):
name = models.CharField(max_length=50, blank=True)
description = models.TextField(blank=True)
node_tree = models.ForeignKey(NodeTree, db_index = True)
unique_name = models.TextField(unique=True, blank=True)
last_updated_timestamp = models.DateTimeField('date last updated', blank=True)
class ConceptNode(Node):
node_parent = models.ForeignKey(Node, related_name="nodeParent", null=True, blank=True)
class DerivedNode(Node):
node_source = models.ForeignKey(Node, related_name="nodeSource")
node_target = models.ForeignKey(Node, related_name="nodeTarget")
Из соображений производительности я использую select_related(depth = 2) всякий раз, когда я извлекаю большой выбор элементов NodeData. Однако select_related не отслеживает отношения вплоть до подклассов, поэтому следующий код* приводит к вызову реализации myFunction ConceptNode без предварительно выбранных данных для объекта ConceptNode, используемого в этой функции:
nd = NodeData.objects.get(id = 1)
nd.node.conceptnode.myFunction()
Это делает select_related не таким уж полезным, так как многие функции вызываются таким образом, и они не пользуются преимуществами данных, кэшированных select_related.
Мой вопрос: могу ли я заставить select_related получить эту информацию для меня, чтобы каждый объект NodeData, который я получаю, имел кэшированные экземпляры Node и ConceptNode/DerivedNode?*
ПРИМЕЧАНИЕ. На самом деле это делается с использованием модели функций доступа, как я спрашивал о здесь
ПРИМЕЧАНИЕ. То, что я пытаюсь сделать, похоже на this, но немного отличается, потому что у меня есть несколько подклассов.
EDIT: благодаря подсказке от chris-platt я обнаружил, что следующее делает то, что мне нужно:
nd = NodeData.objects.select_related('conceptnode','derivednode').get(id = 1)
nd.node.conceptnode.myFunction()
Первая строка предварительно загружает экземпляр DerivedNode или ConceptNode в соответствующий объект кэша.