diff options
Diffstat (limited to 'django/db')
| -rw-r--r-- | django/db/models/base.py | 5 | ||||
| -rw-r--r-- | django/db/models/manager.py | 2 | ||||
| -rw-r--r-- | django/db/models/options.py | 9 | ||||
| -rw-r--r-- | django/db/models/sql/query.py | 28 |
4 files changed, 37 insertions, 7 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py index 05cd0d9ea1..3a3fbf16ac 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -116,6 +116,8 @@ class ModelBase(type): new_class._meta.local_many_to_many): raise FieldError("Proxy model '%s' contains model fields." % name) + while base._meta.proxy: + base = base._meta.proxy_for_model new_class._meta.setup_proxy(base) # Do the appropriate setup for any model parents. @@ -123,6 +125,7 @@ class ModelBase(type): if isinstance(f, OneToOneField)]) for base in parents: + original_base = base if not hasattr(base, '_meta'): # Things without _meta aren't functional models, so they're # uninteresting parents. @@ -167,7 +170,7 @@ class ModelBase(type): # Proxy models inherit the non-abstract managers from their base, # unless they have redefined any of them. if is_proxy: - new_class.copy_managers(base._meta.concrete_managers) + new_class.copy_managers(original_base._meta.concrete_managers) # Inherit virtual fields (like GenericForeignKey) from the parent # class diff --git a/django/db/models/manager.py b/django/db/models/manager.py index 57844f28fe..52612d8f64 100644 --- a/django/db/models/manager.py +++ b/django/db/models/manager.py @@ -57,7 +57,7 @@ class Manager(object): setattr(model, name, ManagerDescriptor(self)) if not getattr(model, '_default_manager', None) or self.creation_counter < model._default_manager.creation_counter: model._default_manager = self - if model._meta.abstract or self._inherited: + if model._meta.abstract or (self._inherited and not self.model._meta.proxy): model._meta.abstract_managers.append((self.creation_counter, name, self)) else: diff --git a/django/db/models/options.py b/django/db/models/options.py index c7ae983541..34dd2aac34 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -461,8 +461,13 @@ class Options(object): 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] + # Tries to get a link field from the immediate parent + parent_link = parent._meta.get_ancestor_link(ancestor) + if parent_link: + # In case of a proxied model, the first link + # of the chain to the ancestor is that parent + # links + return self.parents[parent] or parent_link def get_ordered_objects(self): "Returns a list of Options objects that are ordered with respect to this object." diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index bafa1e93ea..394e30ba97 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -778,7 +778,9 @@ class BaseQuery(object): qn2 = self.connection.ops.quote_name aliases = set() only_load = self.deferred_to_columns() - proxied_model = opts.proxy and opts.proxy_for_model or 0 + # Skip all proxy to the root proxied model + proxied_model = get_proxied_model(opts) + if start_alias: seen = {None: start_alias} for field, model in opts.get_fields_with_model(): @@ -1301,7 +1303,10 @@ class BaseQuery(object): opts = self.model._meta root_alias = self.tables[0] seen = {None: root_alias} - proxied_model = opts.proxy and opts.proxy_for_model or 0 + + # Skip all proxy to the root proxied model + proxied_model = get_proxied_model(opts) + for field, model in opts.get_fields_with_model(): if model not in seen: if model is proxied_model: @@ -1376,6 +1381,13 @@ class BaseQuery(object): alias = root_alias alias_chain = [] for int_model in opts.get_base_chain(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 lhs_col = int_opts.parents[int_model].column dedupe = lhs_col in opts.duplicate_targets if dedupe: @@ -1720,7 +1732,9 @@ class BaseQuery(object): raise MultiJoin(pos + 1) if model: # The field lives on a base class of the current model. - proxied_model = opts.proxy and opts.proxy_for_model or 0 + # Skip the chain of proxy to the concrete proxied model + proxied_model = get_proxied_model(opts) + for int_model in opts.get_base_chain(model): if int_model is proxied_model: opts = int_model._meta @@ -2423,3 +2437,11 @@ def add_to_dict(data, key, value): data[key].add(value) else: data[key] = set([value]) + +def get_proxied_model(opts): + int_opts = opts + proxied_model = None + while int_opts.proxy: + proxied_model = int_opts.proxy_for_model + int_opts = proxied_model._meta + return proxied_model |
