summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Johnson <me@adamj.eu>2024-03-08 22:01:11 +0000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2024-03-11 06:52:50 +0100
commite5ec11a84d6f3725220360e893050cb00403a22e (patch)
tree23e878a30ed1c1876ab1532c81c2e8eef663b8b1
parent894fa55da1ff05229391da6a2b3dfc2bb2876eb0 (diff)
Fixed #35285 -- Optimized ForeignObject._check_unique_target().
-rw-r--r--django/db/models/fields/related.py98
1 files changed, 47 insertions, 51 deletions
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index f903dc2f22..3e4bfe34c1 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -615,60 +615,56 @@ class ForeignObject(RelatedField):
if not self.foreign_related_fields:
return []
- unique_foreign_fields = {
- frozenset([f.name])
- for f in self.remote_field.model._meta.get_fields()
- if getattr(f, "unique", False)
- }
- unique_foreign_fields.update(
- {frozenset(ut) for ut in self.remote_field.model._meta.unique_together}
- )
- unique_foreign_fields.update(
- {
- frozenset(uc.fields)
- for uc in self.remote_field.model._meta.total_unique_constraints
- }
+ has_unique_constraint = any(
+ rel_field.unique for rel_field in self.foreign_related_fields
)
- foreign_fields = {f.name for f in self.foreign_related_fields}
- has_unique_constraint = any(u <= foreign_fields for u in unique_foreign_fields)
-
- if not has_unique_constraint and len(self.foreign_related_fields) > 1:
- field_combination = ", ".join(
- "'%s'" % rel_field.name for rel_field in self.foreign_related_fields
+ if not has_unique_constraint:
+ foreign_fields = {f.name for f in self.foreign_related_fields}
+ remote_opts = self.remote_field.model._meta
+ has_unique_constraint = any(
+ frozenset(ut) <= foreign_fields for ut in remote_opts.unique_together
+ ) or any(
+ frozenset(uc.fields) <= foreign_fields
+ for uc in remote_opts.total_unique_constraints
)
- model_name = self.remote_field.model.__name__
- return [
- checks.Error(
- "No subset of the fields %s on model '%s' is unique."
- % (field_combination, model_name),
- hint=(
- "Mark a single field as unique=True or add a set of "
- "fields to a unique constraint (via unique_together "
- "or a UniqueConstraint (without condition) in the "
- "model Meta.constraints)."
- ),
- obj=self,
- id="fields.E310",
- )
- ]
- elif not has_unique_constraint:
- field_name = self.foreign_related_fields[0].name
- model_name = self.remote_field.model.__name__
- return [
- checks.Error(
- "'%s.%s' must be unique because it is referenced by "
- "a foreign key." % (model_name, field_name),
- hint=(
- "Add unique=True to this field or add a "
- "UniqueConstraint (without condition) in the model "
- "Meta.constraints."
- ),
- obj=self,
- id="fields.E311",
+
+ if not has_unique_constraint:
+ if len(self.foreign_related_fields) > 1:
+ field_combination = ", ".join(
+ f"'{rel_field.name}'" for rel_field in self.foreign_related_fields
)
- ]
- else:
- return []
+ model_name = self.remote_field.model.__name__
+ return [
+ checks.Error(
+ f"No subset of the fields {field_combination} on model "
+ f"'{model_name}' is unique.",
+ hint=(
+ "Mark a single field as unique=True or add a set of "
+ "fields to a unique constraint (via unique_together "
+ "or a UniqueConstraint (without condition) in the "
+ "model Meta.constraints)."
+ ),
+ obj=self,
+ id="fields.E310",
+ )
+ ]
+ else:
+ field_name = self.foreign_related_fields[0].name
+ model_name = self.remote_field.model.__name__
+ return [
+ checks.Error(
+ f"'{model_name}.{field_name}' must be unique because it is "
+ "referenced by a foreign key.",
+ hint=(
+ "Add unique=True to this field or add a "
+ "UniqueConstraint (without condition) in the model "
+ "Meta.constraints."
+ ),
+ obj=self,
+ id="fields.E311",
+ )
+ ]
+ return []
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()