diff options
| author | Julien Hartmann <julien@etherdream.org> | 2016-06-23 17:10:52 +0700 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2016-07-11 13:30:44 -0400 |
| commit | f4afb85d7e900123fa8f88110adc011ab184e153 (patch) | |
| tree | c917ef85c486c4f399ea1076178b7034eb7fcbb5 | |
| parent | 418658f453bed7fe7949dda26651aab370003e6a (diff) | |
Fixed #26749 -- Preserved behavior of use_for_related_field during deprecation.
| -rw-r--r-- | django/db/models/fields/related_descriptors.py | 6 | ||||
| -rw-r--r-- | docs/releases/1.10.txt | 6 | ||||
| -rw-r--r-- | tests/managers_regress/tests.py | 97 |
3 files changed, 102 insertions, 7 deletions
diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index c217b9b2b0..de36d4a8e5 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -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 " diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index c56ac6efc6..b7b2813b31 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -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 ------------- diff --git a/tests/managers_regress/tests.py b/tests/managers_regress/tests.py index 7c1223a5f1..feaca1cba0 100644 --- a/tests/managers_regress/tests.py +++ b/tests/managers_regress/tests.py @@ -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 |
