summaryrefslogtreecommitdiff
path: root/django/db/models/sql/query.py
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2012-12-17 14:02:41 +0200
committerAnssi Kääriäinen <akaariai@gmail.com>2012-12-30 11:19:35 +0200
commit68985db48212c701a3d975636123a5d79bdc006f (patch)
tree9272ad672f0a9762dee77ba39a0888a5b003b5f3 /django/db/models/sql/query.py
parent4511aeb6b8b843ee913fb43a37c9686980210948 (diff)
Added Query.join_parent_model()
This simplifies especially compiler.py a lot, where almost the same code was repeated multiple times. Refs #19385
Diffstat (limited to 'django/db/models/sql/query.py')
-rw-r--r--django/db/models/sql/query.py36
1 files changed, 32 insertions, 4 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index e5833b2b51..2546d6c889 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -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