Ticket #17678: 17678.diff

File 17678.diff, 5.1 KB (added by akaariai, 4 years ago)
  • django/contrib/contenttypes/models.py

    diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py
    index 6d919b4..6e99632 100644
    a b class ContentTypeManager(models.Manager): 
    1717        return ct
    1818
    1919    def _get_opts(self, model):
    20         opts = model._meta
    21         while opts.proxy:
    22             model = opts.proxy_for_model
    23             opts = model._meta
    24         return opts
     20        return model._meta.concrete_class._meta
    2521
    2622    def _get_from_cache(self, opts):
    2723        key = (opts.app_label, opts.object_name.lower())
  • django/db/models/base.py

    diff --git a/django/db/models/base.py b/django/db/models/base.py
    index ebd67be..1810abd 100644
    a b class ModelBase(type): 
    122122            if (new_class._meta.local_fields or
    123123                    new_class._meta.local_many_to_many):
    124124                raise FieldError("Proxy model '%s' contains model fields." % name)
    125             while base._meta.proxy:
    126                 base = base._meta.proxy_for_model
    127125            new_class._meta.setup_proxy(base)
     126            new_class._meta.concrete_class = base._meta.concrete_class
     127        else:
     128            new_class._meta.concrete_class = new_class
    128129
    129130        # Do the appropriate setup for any model parents.
    130131        o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields
    class ModelBase(type): 
    149150                                        (field.name, name, base.__name__))
    150151            if not base._meta.abstract:
    151152                # Concrete classes...
    152                 while base._meta.proxy:
    153                     # Skip over a proxy class to the "real" base it proxies.
    154                     base = base._meta.proxy_for_model
     153                base = base._meta.concrete_class
    155154                if base in o2o_map:
    156155                    field = o2o_map[base]
    157156                elif not is_proxy:
  • django/db/models/options.py

    diff --git a/django/db/models/options.py b/django/db/models/options.py
    index 0cd52a3..ba3685a 100644
    a b class Options(object): 
    4040        self.abstract = False
    4141        self.managed = True
    4242        self.proxy = False
     43        # For any class which is a proxy (including automatically created
     44        # classes for deferred object loading) the proxy_for_model tells
     45        # which class this model is proxying. Note that proxy_for_model
     46        # can create a chain of proxy models. For non-proxy models the
     47        # variable is always None.
    4348        self.proxy_for_model = None
     49        # For any non-abstract class the concrete class is the model
     50        # in the end of the proxy_for_model chain. In particular, for
     51        # concrete models the concrete_model is always the class itself.
     52        self.concrete_class = None
    4453        self.parents = SortedDict()
    4554        self.duplicate_targets = {}
    4655        self.auto_created = False
  • django/db/models/sql/query.py

    diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
    index a78df34..f7cac1e 100644
    a b class Query(object): 
    575575            return
    576576        orig_opts = self.model._meta
    577577        seen = {}
    578         if orig_opts.proxy:
    579             must_include = {orig_opts.proxy_for_model: set([orig_opts.pk])}
    580         else:
    581             must_include = {self.model: set([orig_opts.pk])}
     578        # NOTE: This does what the previous code did. Is this correct? The
     579        # code below is a bit hard to grasp...
     580        must_include = {orig_opts.concrete_class: set([orig_opts.pk])}
    582581        for field_name in field_names:
    583582            parts = field_name.split(LOOKUP_SEP)
    584583            cur_model = self.model
    class Query(object): 
    586585            for name in parts[:-1]:
    587586                old_model = cur_model
    588587                source = opts.get_field_by_name(name)[0]
    589                 cur_model = opts.get_field_by_name(name)[0].rel.to
     588                cur_model = source.rel.to
    590589                opts = cur_model._meta
    591590                # Even if we're "just passing through" this model, we must add
    592591                # both the current model's pk and the related reference field
    def add_to_dict(data, key, value): 
    19921991        data[key] = set([value])
    19931992
    19941993def get_proxied_model(opts):
    1995     int_opts = opts
    1996     proxied_model = None
    1997     while int_opts.proxy:
    1998         proxied_model = int_opts.proxy_for_model
    1999         int_opts = proxied_model._meta
    2000     return proxied_model
     1994    return opts.concrete_class
  • tests/modeltests/proxy_models/tests.py

    diff --git a/tests/modeltests/proxy_models/tests.py b/tests/modeltests/proxy_models/tests.py
    index 3ec8465..15c5dc0 100644
    a b class ProxyModelTests(TestCase): 
    232232        resp = [u.name for u in UserProxyProxy.objects.all()]
    233233        self.assertEqual(resp, ['Bruce'])
    234234
     235    def test_proxy_for_model(self):
     236        self.assertEquals(UserProxy, UserProxyProxy._meta.proxy_for_model)
     237
    235238    def test_proxy_delete(self):
    236239        """
    237240        Proxy objects can be deleted
Back to Top