diff options
| author | Adam Johnson <me@adamj.eu> | 2024-03-08 22:01:11 +0000 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2024-03-11 06:52:50 +0100 |
| commit | e5ec11a84d6f3725220360e893050cb00403a22e (patch) | |
| tree | 23e878a30ed1c1876ab1532c81c2e8eef663b8b1 | |
| parent | 894fa55da1ff05229391da6a2b3dfc2bb2876eb0 (diff) | |
Fixed #35285 -- Optimized ForeignObject._check_unique_target().
| -rw-r--r-- | django/db/models/fields/related.py | 98 |
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() |
