Kaydet (Commit) f7dba618 authored tarafından Anssi Kääriäinen's avatar Anssi Kääriäinen

Avoided creation of deferred model from another deferred model

Also never create deferred model when no attrs are deferred.
üst 5b0375ec
......@@ -186,6 +186,14 @@ def deferred_class_factory(model, attrs):
being replaced with DeferredAttribute objects. The "pk_value" ties the
deferred attributes to a particular instance of the model.
"""
if not attrs:
return model
# Never create deferred models based on deferred model
if model._deferred:
# Deferred models are proxies for the non-deferred model. We never
# create chains of defers => proxy_for_model is the non-deferred
# model.
model = model._meta.proxy_for_model
# The app registry wants a unique name for each model, otherwise the new
# class won't be created (we get an exception). Therefore, we generate
# the name using the passed in attrs. It's OK to reuse an existing class
......
......@@ -6,6 +6,7 @@ from django.apps import apps
from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.backends.db import SessionStore
from django.db.models import Count
from django.db.models.query_utils import deferred_class_factory, DeferredAttribute
from django.test import TestCase, override_settings
from .models import (
......@@ -233,7 +234,6 @@ class DeferRegressionTest(TestCase):
self.assertEqual(len(qs), 1)
def test_deferred_class_factory(self):
from django.db.models.query_utils import deferred_class_factory
new_class = deferred_class_factory(
Item,
('this_is_some_very_long_attribute_name_so_modelname_truncation_is_triggered',))
......@@ -241,6 +241,17 @@ class DeferRegressionTest(TestCase):
new_class.__name__,
'Item_Deferred_this_is_some_very_long_attribute_nac34b1f495507dad6b02e2cb235c875e')
def test_deferred_class_factory_already_deferred(self):
deferred_item1 = deferred_class_factory(Item, ('name',))
deferred_item2 = deferred_class_factory(deferred_item1, ('value',))
self.assertIs(deferred_item2._meta.proxy_for_model, Item)
self.assertFalse(isinstance(deferred_item2.__dict__.get('name'), DeferredAttribute))
self.assertTrue(isinstance(deferred_item2.__dict__.get('value'), DeferredAttribute))
def test_deferred_class_factory_no_attrs(self):
deferred_cls = deferred_class_factory(Item, ())
self.assertFalse(deferred_cls._deferred)
class DeferAnnotateSelectRelatedTest(TestCase):
def test_defer_annotate_select_related(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment