﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
20776	Multi-level Multi-table Inheritance - mismatched PKs / explicit db_columns	dowstreet@…	nobody	"There seems to be a problem with queries that (i) span several levels of multi-table inheritance subclassing when (ii) PKs do not match all the way up the hierarchy.  This situation can arise when a higher level object (e.g. parent) is created before a lower level object (e.g. grandchild).  The query seems to use the PK of the grandchild's parent instead of walking the whole way up the hierarchy when looking up fields that are stored in the grandparent table.

In the example below there are three levels in the class hierarchy.  When accessing the name field (which is stored in the Level1 base class) from an object in Level3, the query returns an unexpected value 'Top 1' instead of the expected 'Bot 1':

{{{

# models.py

from django.db import models

class Level1(models.Model):
 """""" Top level base class """"""

 level1_id = models.AutoField(primary_key=True, db_column='Level1_ID')
 name = models.CharField(max_length=32, db_column='Name', blank=True, null=True)

 class Meta:
     db_table = 'Level1'


class Level2(Level1):
 """""" Middle level class """"""

 level2_id = models.AutoField(primary_key=True, db_column='Level2_ID')
 level1 = models.OneToOneField('Level1', db_column='Level1_ID', parent_link=True)  # parent class

 class Meta:
     db_table = 'Level2'


class Level3(Level2):
 """""" Bottom level class """"""

 level3_id = models.AutoField(primary_key=True, db_column='Level3_ID')
 level2 = models.OneToOneField('Level2', db_column='Level2_ID', parent_link=True)  # parent class

 class Meta:
     db_table = 'Level3'

}}}

Using the shell to add a Level1 object and then a Level3 object to an otherwise empty database:

{{{

from sc_test.models import *

>>> top1 = Level1()
>>> top1.name = 'Top 1'
>>> top1.save()

>>> bot1 = Level3()
>>> bot1.name = 'Bot 1'
>>> bot1.save()

>>> l1 = Level1.objects.all()
>>> l1
[<Level1: Level1 object>, <Level1: Level1 object>]

>>> l2 = Level2.objects.all()
>>> l2
[<Level2: Level2 object>]

>>> l3 = Level3.objects.all()
>>> l3
[<Level3: Level3 object>]

>>> l1[0].name
u'Top 1'

>>> l1[1].name
u'Bot 1'

>>> l2[0].name
u'Bot 1'

>>> l3[0].name
u'Top 1'                               # WRONG!! - expected value is u'Bot 1'

}}}

Note: In this example OneToOneField and ID/primary keys are manually added so that specific db_column names can be used.  It is unclear whether the problem is related to this combination, or whether it affects auto-generated OneToOneFields as well.  "	Cleanup/optimization	closed	Database layer (models, ORM)	1.5	Normal	invalid	Muti-table Inheritance		Accepted	0	0	0	0	0	0
