summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2015-10-07 15:29:20 -0400
committerSimon Charette <charette.s@gmail.com>2015-10-12 12:14:27 -0400
commit5b980897f2da3c048d88029af554e0fc4be68a8e (patch)
tree8eae3580b0bfa8c48025b0f41ad9f1be6cf8c787 /django
parent211486f3ab5602cdc332f03cd03fad3cb929d154 (diff)
Refs #18012 -- Made proxy and concrete model reverse fields consistent.
Prior to this change proxy models reverse fields didn't include the reverse fields pointing to their concrete model.
Diffstat (limited to 'django')
-rw-r--r--django/db/models/deletion.py2
-rw-r--r--django/db/models/options.py14
2 files changed, 5 insertions, 11 deletions
diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index 76a2d35890..831e3c03db 100644
--- a/django/db/models/deletion.py
+++ b/django/db/models/deletion.py
@@ -55,7 +55,7 @@ def get_candidate_relations_to_delete(opts):
# The candidate relations are the ones that come from N-1 and 1-1 relations.
# N-N (i.e., many-to-many) relations aren't candidates for deletion.
return (
- f for f in opts.concrete_model._meta.get_fields(include_hidden=True)
+ f for f in opts.get_fields(include_hidden=True)
if f.auto_created and not f.concrete and (f.one_to_one or f.one_to_many)
)
diff --git a/django/db/models/options.py b/django/db/models/options.py
index 28773bc0b3..3d0a42e515 100644
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -552,14 +552,10 @@ class Options(object):
is set as a property on every model.
"""
related_objects_graph = defaultdict(list)
- # Map of concrete models to all options of models it represents.
- # Including its options and all its proxy model ones.
- concrete_model_classes = defaultdict(list)
all_models = self.apps.get_models(include_auto_created=True)
for model in all_models:
opts = model._meta
- concrete_model_classes[opts.concrete_model].append(opts)
# Abstract model's fields are copied to child models, hence we will
# see the fields from the child models.
if opts.abstract:
@@ -570,7 +566,7 @@ class Options(object):
)
for f in fields_with_relations:
if not isinstance(f.remote_field.model, six.string_types):
- related_objects_graph[f.remote_field.model._meta].append(f)
+ related_objects_graph[f.remote_field.model._meta.concrete_model._meta].append(f)
for model in all_models:
# Set the relation_tree using the internal __dict__. In this way
@@ -578,9 +574,7 @@ class Options(object):
# __dict__ takes precedence over a data descriptor (such as
# @cached_property). This means that the _meta._relation_tree is
# only called if related_objects is not in __dict__.
- related_objects = list(chain.from_iterable(
- related_objects_graph[opts] for opts in concrete_model_classes[model]
- ))
+ related_objects = related_objects_graph[model._meta.concrete_model._meta]
model._meta.__dict__['_relation_tree'] = related_objects
# It seems it is possible that self is not in all_models, so guard
# against that with default for get().
@@ -674,10 +668,10 @@ class Options(object):
for obj in parent._meta._get_fields(
forward=forward, reverse=reverse, include_parents=include_parents,
include_hidden=include_hidden, seen_models=seen_models):
- if hasattr(obj, 'parent_link') and obj.parent_link:
+ if getattr(obj, 'parent_link', False) and obj.model != self.concrete_model:
continue
fields.append(obj)
- if reverse:
+ if reverse and not self.proxy:
# Tree is computed once and cached until the app cache is expired.
# It is composed of a list of fields pointing to the current model
# from other models.