Browse Source

Refs #16055 -- Deprecated get_joining_columns()/get_reverse_joining_columns() methods.

David Wobrock 1 year ago
parent
commit
8b1ff0da4b

+ 12 - 0
django/db/models/fields/related.py

@@ -1,5 +1,6 @@
 import functools
 import inspect
+import warnings
 from functools import partial
 
 from django import forms
@@ -13,6 +14,7 @@ from django.db.models.constants import LOOKUP_SEP
 from django.db.models.deletion import CASCADE, SET_DEFAULT, SET_NULL
 from django.db.models.query_utils import PathInfo
 from django.db.models.utils import make_model_tuple
+from django.utils.deprecation import RemovedInDjango60Warning
 from django.utils.functional import cached_property
 from django.utils.translation import gettext_lazy as _
 
@@ -777,12 +779,22 @@ class ForeignObject(RelatedField):
         return attname, None
 
     def get_joining_columns(self, reverse_join=False):
+        warnings.warn(
+            "ForeignObject.get_joining_columns() is deprecated. Use "
+            "get_joining_fields() instead.",
+            RemovedInDjango60Warning,
+        )
         source = self.reverse_related_fields if reverse_join else self.related_fields
         return tuple(
             (lhs_field.column, rhs_field.column) for lhs_field, rhs_field in source
         )
 
     def get_reverse_joining_columns(self):
+        warnings.warn(
+            "ForeignObject.get_reverse_joining_columns() is deprecated. Use "
+            "get_reverse_joining_fields() instead.",
+            RemovedInDjango60Warning,
+        )
         return self.get_joining_columns(reverse_join=True)
 
     def get_joining_fields(self, reverse_join=False):

+ 7 - 0
django/db/models/fields/reverse_related.py

@@ -8,8 +8,10 @@ in the ``remote_field`` attribute of the field.
 They also act as reverse fields for the purposes of the Meta API because
 they're the closest concept currently available.
 """
+import warnings
 
 from django.core import exceptions
+from django.utils.deprecation import RemovedInDjango60Warning
 from django.utils.functional import cached_property
 from django.utils.hashable import make_hashable
 
@@ -193,6 +195,11 @@ class ForeignObjectRel(FieldCacheMixin):
         return bool(self.related_name) and self.related_name[-1] == "+"
 
     def get_joining_columns(self):
+        warnings.warn(
+            "ForeignObjectRel.get_joining_columns() is deprecated. Use "
+            "get_joining_fields() instead.",
+            RemovedInDjango60Warning,
+        )
         return self.field.get_reverse_joining_columns()
 
     def get_joining_fields(self):

+ 12 - 0
django/db/models/sql/datastructures.py

@@ -2,8 +2,11 @@
 Useful auxiliary data structures for query construction. Not useful outside
 the SQL domain.
 """
+import warnings
+
 from django.core.exceptions import FullResultSet
 from django.db.models.sql.constants import INNER, LOUTER
+from django.utils.deprecation import RemovedInDjango60Warning
 
 
 class MultiJoin(Exception):
@@ -68,6 +71,11 @@ class Join:
                 for lhs_field, rhs_field in self.join_fields
             )
         else:
+            warnings.warn(
+                "The usage of get_joining_columns() in Join is deprecated. Implement "
+                "get_joining_fields() instead.",
+                RemovedInDjango60Warning,
+            )
             self.join_fields = None
             self.join_cols = join_field.get_joining_columns()
         # Along which field (or ForeignObjectRel in the reverse join case)
@@ -87,9 +95,13 @@ class Join:
         qn = compiler.quote_name_unless_alias
         qn2 = connection.ops.quote_name
         # Add a join condition for each pair of joining columns.
+        # RemovedInDjango60Warning: when the depraction ends, replace with:
+        # for lhs, rhs in self.join_field:
         join_fields = self.join_fields or self.join_cols
         for lhs, rhs in join_fields:
             if isinstance(lhs, str):
+                # RemovedInDjango60Warning: when the depraction ends, remove
+                # the branch for strings.
                 lhs_full_name = "%s.%s" % (qn(self.parent_alias), qn2(lhs))
                 rhs_full_name = "%s.%s" % (qn(self.table_alias), qn2(rhs))
             else:

+ 8 - 0
docs/internals/deprecation.txt

@@ -24,6 +24,14 @@ details on these changes.
 * ``request`` will be required in the signature of
   ``ModelAdmin.lookup_allowed()`` subclasses.
 
+* The ``django.db.models.sql.datastructures.Join`` will no longer fallback to
+  ``get_joining_columns()``.
+
+* The ``get_joining_columns()`` method of ``ForeignObject`` and
+  ``ForeignObjectRel`` will be removed.
+
+* The ``ForeignObject.get_reverse_joining_columns()`` method will be removed.
+
 .. _deprecation-removed-in-5.1:
 
 5.1

+ 8 - 0
docs/releases/5.0.txt

@@ -391,6 +391,14 @@ Miscellaneous
   Support for ``ModelAdmin`` subclasses that do not accept this argument is
   deprecated.
 
+* The ``get_joining_columns()`` method of ``ForeignObject`` and
+  ``ForeignObjectRel`` is deprecated. Starting with Django 6.0,
+  ``django.db.models.sql.datastructures.Join`` will no longer fallback to
+  ``get_joining_columns()``. Subclasses should implement
+  ``get_joining_fields()`` instead.
+
+* The ``ForeignObject.get_reverse_joining_columns()`` method is deprecated.
+
 Features removed in 5.0
 =======================
 

+ 47 - 0
tests/foreign_object/tests.py

@@ -8,6 +8,7 @@ from django.db import models
 from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
 from django.test.utils import isolate_apps
 from django.utils import translation
+from django.utils.deprecation import RemovedInDjango60Warning
 
 from .models import (
     Article,
@@ -687,3 +688,49 @@ class TestCachedPathInfo(TestCase):
         foreign_object_restored = pickle.loads(pickle.dumps(foreign_object))
         self.assertIn("path_infos", foreign_object_restored.__dict__)
         self.assertIn("reverse_path_infos", foreign_object_restored.__dict__)
+
+
+class GetJoiningDeprecationTests(TestCase):
+    def test_foreign_object_get_joining_columns_warning(self):
+        msg = (
+            "ForeignObject.get_joining_columns() is deprecated. Use "
+            "get_joining_fields() instead."
+        )
+        with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
+            Membership.person.field.get_joining_columns()
+
+    def test_foreign_object_get_reverse_joining_columns_warning(self):
+        msg = (
+            "ForeignObject.get_reverse_joining_columns() is deprecated. Use "
+            "get_reverse_joining_fields() instead."
+        )
+        with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
+            Membership.person.field.get_reverse_joining_columns()
+
+    def test_foreign_object_rel_get_joining_columns_warning(self):
+        msg = (
+            "ForeignObjectRel.get_joining_columns() is deprecated. Use "
+            "get_joining_fields() instead."
+        )
+        with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
+            Membership.person.field.remote_field.get_joining_columns()
+
+    def test_join_get_joining_columns_warning(self):
+        class CustomForeignKey(models.ForeignKey):
+            def __getattribute__(self, attr):
+                if attr == "get_joining_fields":
+                    raise AttributeError
+                return super().__getattribute__(attr)
+
+        class CustomParent(models.Model):
+            value = models.CharField(max_length=255)
+
+        class CustomChild(models.Model):
+            links = CustomForeignKey(CustomParent, models.CASCADE)
+
+        msg = (
+            "The usage of get_joining_columns() in Join is deprecated. Implement "
+            "get_joining_fields() instead."
+        )
+        with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
+            CustomChild.objects.filter(links__value="value")