Added Query.join_parent_model()

This simplifies especially compiler.py a lot, where almost the same
code was repeated multiple times.

Refs #19385
This commit is contained in:
Anssi Kääriäinen 2012-12-17 14:02:41 +02:00
parent 4511aeb6b8
commit 68985db482
2 changed files with 37 additions and 61 deletions

View file

@ -1004,12 +1004,40 @@ class Query(object):
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, link_field.column,
model._meta.pk.column), join_field=link_field)
self.join_parent_model(opts, model, root_alias, seen)
self.included_inherited_models = seen
def join_parent_model(self, opts, model, alias, seen):
"""
Makes sure the given 'model' is joined in the query. If 'model' isn't
a parent of 'opts' or if it is None this method is a no-op.
The 'alias' is the root alias for starting the join, 'seen' is a dict
of model -> alias of existing joins.
"""
if model in seen:
return seen[model]
int_opts = opts
chain = opts.get_base_chain(model)
if chain is None:
return alias
for int_model in chain:
if int_model in seen:
return seen[int_model]
# Proxy model have elements in base chain
# with no parents, assign the new options
# object and skip to the next base in that
# case
if not int_opts.parents[int_model]:
int_opts = int_model._meta
continue
link_field = int_opts.get_ancestor_link(int_model)
int_opts = int_model._meta
connection = (alias, int_opts.db_table, link_field.column, int_opts.pk.column)
alias = seen[int_model] = self.join(connection, nullable=False,
join_field=link_field)
return alias
def remove_inherited_models(self):
"""
Undoes the effects of setup_inherited_models(). Should be called