Loading django/db/models/options.py +15 −0 Original line number Diff line number Diff line Loading @@ -435,6 +435,21 @@ class Options(object): result.update(parent._meta.get_parent_list()) return result def get_ancestor_link(self, ancestor): """ Returns the field on the current model which points to the given "ancestor". This is possible an indirect link (a pointer to a parent model, which points, eventually, to the ancestor). Used when constructing table joins for model inheritance. Returns None if the model isn't an ancestor of this one. """ if ancestor in self.parents: return self.parents[ancestor] for parent in self.parents: if parent._meta.get_ancestor_link(ancestor): return self.parents[parent] def get_ordered_objects(self): "Returns a list of Options objects that are ordered with respect to this object." if not hasattr(self, '_ordered_objects'): Loading django/db/models/sql/query.py +4 −4 Original line number Diff line number Diff line Loading @@ -643,14 +643,14 @@ class BaseQuery(object): aliases = set() if start_alias: seen = {None: start_alias} root_pk = opts.pk.column for field, model in opts.get_fields_with_model(): if start_alias: try: alias = seen[model] except KeyError: link_field = opts.get_ancestor_link(model) alias = self.join((start_alias, model._meta.db_table, root_pk, model._meta.pk.column)) link_field.column, model._meta.pk.column)) seen[model] = alias else: # If we're starting from the base model of the queryset, the Loading Loading @@ -1156,13 +1156,13 @@ class BaseQuery(object): as_sql()). """ opts = self.model._meta root_pk = opts.pk.column root_alias = self.tables[0] seen = {None: root_alias} for field, model in opts.get_fields_with_model(): if model not in seen: link_field = opts.get_ancestor_link(model) seen[model] = self.join((root_alias, model._meta.db_table, root_pk, model._meta.pk.column)) link_field.column, model._meta.pk.column)) self.included_inherited_models = seen def remove_inherited_models(self): Loading tests/regressiontests/model_inheritance_regress/models.py +19 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,19 @@ class Evaluation(Article): class QualityControl(Evaluation): assignee = models.CharField(max_length=50) class BaseM(models.Model): base_name = models.CharField(max_length=100) def __unicode__(self): return self.base_name class DerivedM(BaseM): customPK = models.IntegerField(primary_key=True) derived_name = models.CharField(max_length=100) def __unicode__(self): return "PK = %d, base_name = %s, derived_name = %s" \ % (self.customPK, self.base_name, self.derived_name) __test__ = {'API_TESTS':""" # Regression for #7350, #7202 Loading Loading @@ -275,4 +288,10 @@ True >>> ArticleWithAuthor.objects.filter(pk=article.pk).update(headline="Oh, no!") 1 >>> DerivedM.objects.create(customPK=44, base_name="b1", derived_name="d1") <DerivedM: PK = 44, base_name = b1, derived_name = d1> >>> DerivedM.objects.all() [<DerivedM: PK = 44, base_name = b1, derived_name = d1>] """} Loading
django/db/models/options.py +15 −0 Original line number Diff line number Diff line Loading @@ -435,6 +435,21 @@ class Options(object): result.update(parent._meta.get_parent_list()) return result def get_ancestor_link(self, ancestor): """ Returns the field on the current model which points to the given "ancestor". This is possible an indirect link (a pointer to a parent model, which points, eventually, to the ancestor). Used when constructing table joins for model inheritance. Returns None if the model isn't an ancestor of this one. """ if ancestor in self.parents: return self.parents[ancestor] for parent in self.parents: if parent._meta.get_ancestor_link(ancestor): return self.parents[parent] def get_ordered_objects(self): "Returns a list of Options objects that are ordered with respect to this object." if not hasattr(self, '_ordered_objects'): Loading
django/db/models/sql/query.py +4 −4 Original line number Diff line number Diff line Loading @@ -643,14 +643,14 @@ class BaseQuery(object): aliases = set() if start_alias: seen = {None: start_alias} root_pk = opts.pk.column for field, model in opts.get_fields_with_model(): if start_alias: try: alias = seen[model] except KeyError: link_field = opts.get_ancestor_link(model) alias = self.join((start_alias, model._meta.db_table, root_pk, model._meta.pk.column)) link_field.column, model._meta.pk.column)) seen[model] = alias else: # If we're starting from the base model of the queryset, the Loading Loading @@ -1156,13 +1156,13 @@ class BaseQuery(object): as_sql()). """ opts = self.model._meta root_pk = opts.pk.column root_alias = self.tables[0] seen = {None: root_alias} for field, model in opts.get_fields_with_model(): if model not in seen: link_field = opts.get_ancestor_link(model) seen[model] = self.join((root_alias, model._meta.db_table, root_pk, model._meta.pk.column)) link_field.column, model._meta.pk.column)) self.included_inherited_models = seen def remove_inherited_models(self): Loading
tests/regressiontests/model_inheritance_regress/models.py +19 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,19 @@ class Evaluation(Article): class QualityControl(Evaluation): assignee = models.CharField(max_length=50) class BaseM(models.Model): base_name = models.CharField(max_length=100) def __unicode__(self): return self.base_name class DerivedM(BaseM): customPK = models.IntegerField(primary_key=True) derived_name = models.CharField(max_length=100) def __unicode__(self): return "PK = %d, base_name = %s, derived_name = %s" \ % (self.customPK, self.base_name, self.derived_name) __test__ = {'API_TESTS':""" # Regression for #7350, #7202 Loading Loading @@ -275,4 +288,10 @@ True >>> ArticleWithAuthor.objects.filter(pk=article.pk).update(headline="Oh, no!") 1 >>> DerivedM.objects.create(customPK=44, base_name="b1", derived_name="d1") <DerivedM: PK = 44, base_name = b1, derived_name = d1> >>> DerivedM.objects.all() [<DerivedM: PK = 44, base_name = b1, derived_name = d1>] """}