Fixed #26749 -- Preserved behavior of use_for_related_field during deprecation.
This commit is contained in:
parent
418658f453
commit
f4afb85d7e
|
@ -109,8 +109,7 @@ class ForwardManyToOneDescriptor(object):
|
||||||
def get_queryset(self, **hints):
|
def get_queryset(self, **hints):
|
||||||
related_model = self.field.remote_field.model
|
related_model = self.field.remote_field.model
|
||||||
|
|
||||||
if (not related_model._meta.base_manager_name and
|
if getattr(related_model._default_manager, 'use_for_related_fields', False):
|
||||||
getattr(related_model._default_manager, 'use_for_related_fields', False)):
|
|
||||||
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
|
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"use_for_related_fields is deprecated, instead "
|
"use_for_related_fields is deprecated, instead "
|
||||||
|
@ -326,8 +325,7 @@ class ReverseOneToOneDescriptor(object):
|
||||||
def get_queryset(self, **hints):
|
def get_queryset(self, **hints):
|
||||||
related_model = self.related.related_model
|
related_model = self.related.related_model
|
||||||
|
|
||||||
if (not related_model._meta.base_manager_name and
|
if getattr(related_model._default_manager, 'use_for_related_fields', False):
|
||||||
getattr(related_model._default_manager, 'use_for_related_fields', False)):
|
|
||||||
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
|
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"use_for_related_fields is deprecated, instead "
|
"use_for_related_fields is deprecated, instead "
|
||||||
|
|
|
@ -1091,6 +1091,12 @@ class to override the manager from the concrete model, or you'll set the
|
||||||
model's ``Meta.manager_inheritance_from_future=True`` option to opt-in to the
|
model's ``Meta.manager_inheritance_from_future=True`` option to opt-in to the
|
||||||
new inheritance behavior.
|
new inheritance behavior.
|
||||||
|
|
||||||
|
During the deprecation period, ``use_for_related_fields`` will be honored and
|
||||||
|
raise a warning, even if a ``base_manager_name`` is set. This allows
|
||||||
|
third-party code to preserve legacy behavior while transitioning to the new
|
||||||
|
API. The warning can be silenced by setting
|
||||||
|
``silence_use_for_related_fields_deprecation=True`` on the manager.
|
||||||
|
|
||||||
Miscellaneous
|
Miscellaneous
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -334,11 +334,26 @@ class TestManagerDeprecations(TestCase):
|
||||||
self.assertEqual(len(warns), 0)
|
self.assertEqual(len(warns), 0)
|
||||||
|
|
||||||
def test_use_for_related_fields_for_many_to_one(self):
|
def test_use_for_related_fields_for_many_to_one(self):
|
||||||
|
# Common objects
|
||||||
|
class MyManagerQuerySet(models.QuerySet):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MyLegacyManagerQuerySet(models.QuerySet):
|
||||||
|
pass
|
||||||
|
|
||||||
class MyManager(models.Manager):
|
class MyManager(models.Manager):
|
||||||
|
def get_queryset(self):
|
||||||
|
return MyManagerQuerySet(model=self.model, using=self._db, hints=self._hints)
|
||||||
|
|
||||||
|
class MyLegacyManager(models.Manager):
|
||||||
use_for_related_fields = True
|
use_for_related_fields = True
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return MyLegacyManagerQuerySet(model=self.model, using=self._db, hints=self._hints)
|
||||||
|
|
||||||
|
# With legacy config there should be a deprecation warning
|
||||||
class MyRelModel(models.Model):
|
class MyRelModel(models.Model):
|
||||||
objects = MyManager()
|
objects = MyLegacyManager()
|
||||||
|
|
||||||
class MyModel(models.Model):
|
class MyModel(models.Model):
|
||||||
fk = models.ForeignKey(MyRelModel, on_delete=models.DO_NOTHING)
|
fk = models.ForeignKey(MyRelModel, on_delete=models.DO_NOTHING)
|
||||||
|
@ -375,16 +390,61 @@ class TestManagerDeprecations(TestCase):
|
||||||
pass
|
pass
|
||||||
self.assertEqual(len(warns), 0)
|
self.assertEqual(len(warns), 0)
|
||||||
|
|
||||||
|
# When mixing base_manager_name and use_for_related_fields, there
|
||||||
|
# should be warnings.
|
||||||
|
class MyRelModel3(models.Model):
|
||||||
|
my_base_manager = MyManager()
|
||||||
|
my_default_manager = MyLegacyManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
base_manager_name = 'my_base_manager'
|
||||||
|
default_manager_name = 'my_default_manager'
|
||||||
|
|
||||||
|
class MyModel3(models.Model):
|
||||||
|
fk = models.ForeignKey(MyRelModel3, on_delete=models.DO_NOTHING)
|
||||||
|
|
||||||
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
|
warnings.simplefilter('always', RemovedInDjango20Warning)
|
||||||
|
try:
|
||||||
|
MyModel3(fk_id=42).fk
|
||||||
|
except DatabaseError:
|
||||||
|
pass
|
||||||
|
self.assertEqual(len(warns), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
str(warns[0].message),
|
||||||
|
"use_for_related_fields is deprecated, "
|
||||||
|
"instead set Meta.base_manager_name on "
|
||||||
|
"'managers_regress.MyRelModel3'.",
|
||||||
|
)
|
||||||
|
with warnings.catch_warnings(record=True):
|
||||||
|
warnings.simplefilter('always', RemovedInDjango20Warning)
|
||||||
|
self.assertIsInstance(MyModel3.fk.get_queryset(), MyLegacyManagerQuerySet)
|
||||||
|
|
||||||
def test_use_for_related_fields_for_one_to_one(self):
|
def test_use_for_related_fields_for_one_to_one(self):
|
||||||
|
# Common objects
|
||||||
|
class MyManagerQuerySet(models.QuerySet):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MyLegacyManagerQuerySet(models.QuerySet):
|
||||||
|
pass
|
||||||
|
|
||||||
class MyManager(models.Manager):
|
class MyManager(models.Manager):
|
||||||
|
def get_queryset(self):
|
||||||
|
return MyManagerQuerySet(model=self.model, using=self._db, hints=self._hints)
|
||||||
|
|
||||||
|
class MyLegacyManager(models.Manager):
|
||||||
use_for_related_fields = True
|
use_for_related_fields = True
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return MyLegacyManagerQuerySet(model=self.model, using=self._db, hints=self._hints)
|
||||||
|
|
||||||
|
# With legacy config there should be a deprecation warning
|
||||||
class MyRelModel(models.Model):
|
class MyRelModel(models.Model):
|
||||||
objects = MyManager()
|
objects = MyLegacyManager()
|
||||||
|
|
||||||
class MyModel(models.Model):
|
class MyModel(models.Model):
|
||||||
o2o = models.OneToOneField(MyRelModel, on_delete=models.DO_NOTHING)
|
o2o = models.OneToOneField(MyRelModel, on_delete=models.DO_NOTHING)
|
||||||
objects = MyManager()
|
objects = MyLegacyManager()
|
||||||
|
|
||||||
with warnings.catch_warnings(record=True) as warns:
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
warnings.simplefilter('always', RemovedInDjango20Warning)
|
warnings.simplefilter('always', RemovedInDjango20Warning)
|
||||||
|
@ -440,6 +500,37 @@ class TestManagerDeprecations(TestCase):
|
||||||
pass
|
pass
|
||||||
self.assertEqual(len(warns), 0)
|
self.assertEqual(len(warns), 0)
|
||||||
|
|
||||||
|
# When mixing base_manager_name and use_for_related_fields, there
|
||||||
|
# should be warnings.
|
||||||
|
class MyRelModel3(models.Model):
|
||||||
|
my_base_manager = MyManager()
|
||||||
|
my_default_manager = MyLegacyManager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
base_manager_name = 'my_base_manager'
|
||||||
|
default_manager_name = 'my_default_manager'
|
||||||
|
|
||||||
|
class MyModel3(models.Model):
|
||||||
|
o2o = models.OneToOneField(MyRelModel3, on_delete=models.DO_NOTHING)
|
||||||
|
|
||||||
|
with warnings.catch_warnings(record=True) as warns:
|
||||||
|
warnings.simplefilter('always', RemovedInDjango20Warning)
|
||||||
|
try:
|
||||||
|
MyModel3(o2o_id=42).o2o
|
||||||
|
except DatabaseError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.assertEqual(len(warns), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
str(warns[0].message),
|
||||||
|
"use_for_related_fields is deprecated, "
|
||||||
|
"instead set Meta.base_manager_name on "
|
||||||
|
"'managers_regress.MyRelModel3'.",
|
||||||
|
)
|
||||||
|
with warnings.catch_warnings(record=True):
|
||||||
|
warnings.simplefilter('always', RemovedInDjango20Warning)
|
||||||
|
self.assertIsInstance(MyModel3.o2o.get_queryset(), MyLegacyManagerQuerySet)
|
||||||
|
|
||||||
def test_legacy_objects_is_created(self):
|
def test_legacy_objects_is_created(self):
|
||||||
class ConcreteParentWithoutManager(models.Model):
|
class ConcreteParentWithoutManager(models.Model):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in New Issue