diff options
| author | Simon Charette <charette.s@gmail.com> | 2015-10-07 15:29:20 -0400 |
|---|---|---|
| committer | Simon Charette <charette.s@gmail.com> | 2015-10-12 12:14:27 -0400 |
| commit | 5b980897f2da3c048d88029af554e0fc4be68a8e (patch) | |
| tree | 8eae3580b0bfa8c48025b0f41ad9f1be6cf8c787 /django | |
| parent | 211486f3ab5602cdc332f03cd03fad3cb929d154 (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.py | 2 | ||||
| -rw-r--r-- | django/db/models/options.py | 14 |
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. |
