Refs #31187 -- Added total_unique_constraints property to model's Options.

This commit is contained in:
Mariusz Felisiak 2020-02-19 08:14:35 +01:00
parent 73a34f3fa8
commit d270c10a72
2 changed files with 20 additions and 9 deletions

View File

@ -19,7 +19,7 @@ from django.db.models import (
NOT_PROVIDED, ExpressionWrapper, IntegerField, Max, Value, NOT_PROVIDED, ExpressionWrapper, IntegerField, Max, Value,
) )
from django.db.models.constants import LOOKUP_SEP from django.db.models.constants import LOOKUP_SEP
from django.db.models.constraints import CheckConstraint, UniqueConstraint from django.db.models.constraints import CheckConstraint
from django.db.models.deletion import CASCADE, Collector from django.db.models.deletion import CASCADE, Collector
from django.db.models.fields.related import ( from django.db.models.fields.related import (
ForeignObjectRel, OneToOneField, lazy_related_operation, resolve_relation, ForeignObjectRel, OneToOneField, lazy_related_operation, resolve_relation,
@ -1023,12 +1023,14 @@ class Model(metaclass=ModelBase):
unique_checks = [] unique_checks = []
unique_togethers = [(self.__class__, self._meta.unique_together)] unique_togethers = [(self.__class__, self._meta.unique_together)]
constraints = [(self.__class__, self._meta.constraints)] constraints = [(self.__class__, self._meta.total_unique_constraints)]
for parent_class in self._meta.get_parent_list(): for parent_class in self._meta.get_parent_list():
if parent_class._meta.unique_together: if parent_class._meta.unique_together:
unique_togethers.append((parent_class, parent_class._meta.unique_together)) unique_togethers.append((parent_class, parent_class._meta.unique_together))
if parent_class._meta.constraints: if parent_class._meta.total_unique_constraints:
constraints.append((parent_class, parent_class._meta.constraints)) constraints.append(
(parent_class, parent_class._meta.total_unique_constraints)
)
for model_class, unique_together in unique_togethers: for model_class, unique_together in unique_togethers:
for check in unique_together: for check in unique_together:
@ -1038,10 +1040,7 @@ class Model(metaclass=ModelBase):
for model_class, model_constraints in constraints: for model_class, model_constraints in constraints:
for constraint in model_constraints: for constraint in model_constraints:
if (isinstance(constraint, UniqueConstraint) and if not any(name in exclude for name in constraint.fields):
# Partial unique constraints can't be validated.
constraint.condition is None and
not any(name in exclude for name in constraint.fields)):
unique_checks.append((model_class, constraint.fields)) unique_checks.append((model_class, constraint.fields))
# These are checks for the unique_for_<date/year/month>. # These are checks for the unique_for_<date/year/month>.

View File

@ -7,7 +7,7 @@ from django.apps import apps
from django.conf import settings from django.conf import settings
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
from django.db import connections from django.db import connections
from django.db.models import AutoField, Manager, OrderWrt from django.db.models import AutoField, Manager, OrderWrt, UniqueConstraint
from django.db.models.query_utils import PathInfo from django.db.models.query_utils import PathInfo
from django.utils.datastructures import ImmutableList, OrderedSet from django.utils.datastructures import ImmutableList, OrderedSet
from django.utils.functional import cached_property from django.utils.functional import cached_property
@ -827,6 +827,18 @@ class Options:
self._get_fields_cache[cache_key] = fields self._get_fields_cache[cache_key] = fields
return fields return fields
@cached_property
def total_unique_constraints(self):
"""
Return a list of total unique constraints. Useful for determining set
of fields guaranteed to be unique for all rows.
"""
return [
constraint
for constraint in self.constraints
if isinstance(constraint, UniqueConstraint) and constraint.condition is None
]
@cached_property @cached_property
def _property_names(self): def _property_names(self):
"""Return a set of the names of the properties defined on the model.""" """Return a set of the names of the properties defined on the model."""