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):
|
||||
related_model = self.field.remote_field.model
|
||||
|
||||
if (not related_model._meta.base_manager_name and
|
||||
getattr(related_model._default_manager, 'use_for_related_fields', False)):
|
||||
if getattr(related_model._default_manager, 'use_for_related_fields', False):
|
||||
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
|
||||
warnings.warn(
|
||||
"use_for_related_fields is deprecated, instead "
|
||||
|
@ -326,8 +325,7 @@ class ReverseOneToOneDescriptor(object):
|
|||
def get_queryset(self, **hints):
|
||||
related_model = self.related.related_model
|
||||
|
||||
if (not related_model._meta.base_manager_name and
|
||||
getattr(related_model._default_manager, 'use_for_related_fields', False)):
|
||||
if getattr(related_model._default_manager, 'use_for_related_fields', False):
|
||||
if not getattr(related_model._default_manager, 'silence_use_for_related_fields_deprecation', False):
|
||||
warnings.warn(
|
||||
"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
|
||||
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
|
||||
-------------
|
||||
|
||||
|
|
|
@ -334,11 +334,26 @@ class TestManagerDeprecations(TestCase):
|
|||
self.assertEqual(len(warns), 0)
|
||||
|
||||
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):
|
||||
def get_queryset(self):
|
||||
return MyManagerQuerySet(model=self.model, using=self._db, hints=self._hints)
|
||||
|
||||
class MyLegacyManager(models.Manager):
|
||||
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):
|
||||
objects = MyManager()
|
||||
objects = MyLegacyManager()
|
||||
|
||||
class MyModel(models.Model):
|
||||
fk = models.ForeignKey(MyRelModel, on_delete=models.DO_NOTHING)
|
||||
|
@ -375,16 +390,61 @@ class TestManagerDeprecations(TestCase):
|
|||
pass
|
||||
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):
|
||||
# Common objects
|
||||
class MyManagerQuerySet(models.QuerySet):
|
||||
pass
|
||||
|
||||
class MyLegacyManagerQuerySet(models.QuerySet):
|
||||
pass
|
||||
|
||||
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
|
||||
|
||||
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):
|
||||
objects = MyManager()
|
||||
objects = MyLegacyManager()
|
||||
|
||||
class MyModel(models.Model):
|
||||
o2o = models.OneToOneField(MyRelModel, on_delete=models.DO_NOTHING)
|
||||
objects = MyManager()
|
||||
objects = MyLegacyManager()
|
||||
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
warnings.simplefilter('always', RemovedInDjango20Warning)
|
||||
|
@ -440,6 +500,37 @@ class TestManagerDeprecations(TestCase):
|
|||
pass
|
||||
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):
|
||||
class ConcreteParentWithoutManager(models.Model):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue