summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/models/base.py14
-rw-r--r--docs/ref/checks.txt3
-rw-r--r--docs/releases/6.0.txt4
-rw-r--r--tests/invalid_models_tests/test_models.py48
4 files changed, 69 insertions, 0 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 36b16c1132..d1321d6540 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -2220,6 +2220,20 @@ class Model(AltersData, metaclass=ModelBase):
id="models.E048",
)
)
+ elif (
+ isinstance(field.remote_field, ForeignObjectRel)
+ and field not in cls._meta.local_concrete_fields
+ and len(field.from_fields) > 1
+ ):
+ errors.append(
+ checks.Error(
+ f"{option!r} refers to a ForeignObject {field_name!r} with "
+ "multiple 'from_fields', which is not supported for that "
+ "option.",
+ obj=cls,
+ id="models.E049",
+ )
+ )
elif field not in cls._meta.local_fields:
errors.append(
checks.Error(
diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt
index ab92220ac9..7735eed478 100644
--- a/docs/ref/checks.txt
+++ b/docs/ref/checks.txt
@@ -443,6 +443,9 @@ Models
* **models.E048**: ``constraints/indexes/unique_together`` refers to a
``CompositePrimaryKey`` ``<field name>``, but ``CompositePrimaryKey``\s are
not supported for that option.
+* **models.E049**: ``constraints/indexes/unique_together`` refers to a
+ ``ForeignObject`` ``<field name>`` with multiple ``from_fields``, which is
+ not supported for that option.
Management Commands
-------------------
diff --git a/docs/releases/6.0.txt b/docs/releases/6.0.txt
index 56e4bf2315..fd30c66121 100644
--- a/docs/releases/6.0.txt
+++ b/docs/releases/6.0.txt
@@ -295,6 +295,10 @@ Models
don't support it (MySQL and MariaDB), the fields are marked as deferred to
trigger a refresh on subsequent accesses.
+* Using a :ref:`ForeignObject <cpk-and-relations>` with multiple
+ ``from_fields`` in Model indexes, constraints, or :attr:`unique_together
+ <django.db.models.Options.unique_together>` now emits a system check error.
+
Pagination
~~~~~~~~~~
diff --git a/tests/invalid_models_tests/test_models.py b/tests/invalid_models_tests/test_models.py
index 5780704eae..2a39e250bd 100644
--- a/tests/invalid_models_tests/test_models.py
+++ b/tests/invalid_models_tests/test_models.py
@@ -166,6 +166,54 @@ class UniqueTogetherTests(SimpleTestCase):
],
)
+ def test_pointing_to_foreign_object(self):
+ class Reference(models.Model):
+ reference_id = models.IntegerField(unique=True)
+
+ class ReferenceTab(models.Model):
+ reference_id = models.IntegerField()
+ reference = models.ForeignObject(
+ Reference,
+ from_fields=["reference_id"],
+ to_fields=["reference_id"],
+ on_delete=models.CASCADE,
+ )
+
+ class Meta:
+ unique_together = [["reference"]]
+
+ self.assertEqual(ReferenceTab.check(), [])
+
+ def test_pointing_to_foreign_object_multi_column(self):
+ class Reference(models.Model):
+ reference_id = models.IntegerField(unique=True)
+ code = models.CharField(max_length=1)
+
+ class ReferenceTabMultiple(models.Model):
+ reference_id = models.IntegerField()
+ code = models.CharField(max_length=1)
+ reference = models.ForeignObject(
+ Reference,
+ from_fields=["reference_id", "code"],
+ to_fields=["reference_id", "code"],
+ on_delete=models.CASCADE,
+ )
+
+ class Meta:
+ unique_together = [["reference"]]
+
+ self.assertEqual(
+ ReferenceTabMultiple.check(),
+ [
+ Error(
+ "'unique_together' refers to a ForeignObject 'reference' with "
+ "multiple 'from_fields', which is not supported for that option.",
+ obj=ReferenceTabMultiple,
+ id="models.E049",
+ ),
+ ],
+ )
+
@isolate_apps("invalid_models_tests")
class IndexesTests(TestCase):