Fixed #35575 -- Added support for constraint validation on GeneratedFields.

This commit is contained in:
Mark Gensler 2024-07-18 08:38:06 +01:00 committed by Sarah Boyce
parent f883bef054
commit 228128618b
7 changed files with 273 additions and 44 deletions

View file

@ -14,6 +14,7 @@ from django.db.models import (
F,
ForeignKey,
Func,
GeneratedField,
IntegerField,
Model,
Q,
@ -32,6 +33,7 @@ try:
from django.contrib.postgres.constraints import ExclusionConstraint
from django.contrib.postgres.fields import (
DateTimeRangeField,
IntegerRangeField,
RangeBoundary,
RangeOperators,
)
@ -866,6 +868,38 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
constraint.validate(RangesModel, RangesModel(ints=(51, 60)))
constraint.validate(RangesModel, RangesModel(ints=(10, 20)), exclude={"ints"})
@skipUnlessDBFeature("supports_stored_generated_columns")
@isolate_apps("postgres_tests")
def test_validate_generated_field_range_adjacent(self):
class RangesModelGeneratedField(Model):
ints = IntegerRangeField(blank=True, null=True)
ints_generated = GeneratedField(
expression=F("ints"),
output_field=IntegerRangeField(null=True),
db_persist=True,
)
with connection.schema_editor() as editor:
editor.create_model(RangesModelGeneratedField)
constraint = ExclusionConstraint(
name="ints_adjacent",
expressions=[("ints_generated", RangeOperators.ADJACENT_TO)],
violation_error_code="custom_code",
violation_error_message="Custom error message.",
)
RangesModelGeneratedField.objects.create(ints=(20, 50))
range_obj = RangesModelGeneratedField(ints=(3, 20))
with self.assertRaisesMessage(ValidationError, "Custom error message."):
constraint.validate(RangesModelGeneratedField, range_obj)
# Excluding referenced or generated field should skip validation.
constraint.validate(RangesModelGeneratedField, range_obj, exclude={"ints"})
constraint.validate(
RangesModelGeneratedField, range_obj, exclude={"ints_generated"}
)
def test_validate_with_custom_code_and_condition(self):
constraint = ExclusionConstraint(
name="ints_adjacent",