Fixed #33902 -- Fixed Meta.constraints validation crash with F() expressions.
Thanks Adam Zahradník for the report.
Bug in 667105877e
.
This commit is contained in:
parent
c614e811f8
commit
63884829ac
|
@ -326,9 +326,12 @@ class UniqueConstraint(BaseConstraint):
|
||||||
# Ignore constraints with excluded fields.
|
# Ignore constraints with excluded fields.
|
||||||
if exclude:
|
if exclude:
|
||||||
for expression in self.expressions:
|
for expression in self.expressions:
|
||||||
for expr in expression.flatten():
|
if hasattr(expression, "flatten"):
|
||||||
if isinstance(expr, F) and expr.name in exclude:
|
for expr in expression.flatten():
|
||||||
return
|
if isinstance(expr, F) and expr.name in exclude:
|
||||||
|
return
|
||||||
|
elif isinstance(expression, F) and expression.name in exclude:
|
||||||
|
return
|
||||||
replacement_map = instance._get_field_value_map(
|
replacement_map = instance._get_field_value_map(
|
||||||
meta=model._meta, exclude=exclude
|
meta=model._meta, exclude=exclude
|
||||||
)
|
)
|
||||||
|
|
|
@ -393,9 +393,7 @@ class BaseExpression:
|
||||||
clone = self.copy()
|
clone = self.copy()
|
||||||
clone.set_source_expressions(
|
clone.set_source_expressions(
|
||||||
[
|
[
|
||||||
references_map.get(expr.name, expr)
|
expr.replace_references(references_map)
|
||||||
if isinstance(expr, F)
|
|
||||||
else expr.replace_references(references_map)
|
|
||||||
for expr in self.get_source_expressions()
|
for expr in self.get_source_expressions()
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -810,6 +808,9 @@ class F(Combinable):
|
||||||
):
|
):
|
||||||
return query.resolve_ref(self.name, allow_joins, reuse, summarize)
|
return query.resolve_ref(self.name, allow_joins, reuse, summarize)
|
||||||
|
|
||||||
|
def replace_references(self, references_map):
|
||||||
|
return references_map.get(self.name, self)
|
||||||
|
|
||||||
def asc(self, **kwargs):
|
def asc(self, **kwargs):
|
||||||
return OrderBy(self, **kwargs)
|
return OrderBy(self, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -29,3 +29,6 @@ Bugfixes
|
||||||
|
|
||||||
* Fixed a regression in Django 4.1 that caused a migration crash on SQLite
|
* Fixed a regression in Django 4.1 that caused a migration crash on SQLite
|
||||||
3.35.5+ when removing an indexed field (:ticket:`33899`).
|
3.35.5+ when removing an indexed field (:ticket:`33899`).
|
||||||
|
|
||||||
|
* Fixed a bug in Django 4.1 that caused a crash of model validation on
|
||||||
|
``UniqueConstraint()`` with field names in ``expressions`` (:ticket:`33902`).
|
||||||
|
|
|
@ -685,6 +685,20 @@ class UniqueConstraintTests(TestCase):
|
||||||
exclude={"color"},
|
exclude={"color"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_validate_expression_str(self):
|
||||||
|
constraint = models.UniqueConstraint("name", name="name_uniq")
|
||||||
|
msg = "Constraint “name_uniq” is violated."
|
||||||
|
with self.assertRaisesMessage(ValidationError, msg):
|
||||||
|
constraint.validate(
|
||||||
|
UniqueConstraintProduct,
|
||||||
|
UniqueConstraintProduct(name=self.p1.name),
|
||||||
|
)
|
||||||
|
constraint.validate(
|
||||||
|
UniqueConstraintProduct,
|
||||||
|
UniqueConstraintProduct(name=self.p1.name),
|
||||||
|
exclude={"name"},
|
||||||
|
)
|
||||||
|
|
||||||
def test_name(self):
|
def test_name(self):
|
||||||
constraints = get_constraints(UniqueConstraintProduct._meta.db_table)
|
constraints = get_constraints(UniqueConstraintProduct._meta.db_table)
|
||||||
expected_name = "name_color_uniq"
|
expected_name = "name_color_uniq"
|
||||||
|
|
Loading…
Reference in New Issue