Skip to content

Commit

Permalink
constraints edits for partial indexes
Browse files Browse the repository at this point in the history
MongoDB doesn't support isnull constraints.
  • Loading branch information
timgraham committed Nov 12, 2024
1 parent 70ba0a1 commit ff43b2b
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 19 deletions.
2 changes: 1 addition & 1 deletion tests/constraints/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Meta:
models.UniqueConstraint(
fields=["name"],
name="name_without_color_uniq",
condition=models.Q(color__isnull=True),
condition=models.Q(color="blue"),
),
]

Expand Down
29 changes: 17 additions & 12 deletions tests/constraints/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,10 +821,10 @@ def test_database_constraint(self):

@skipUnlessDBFeature("supports_partial_indexes")
def test_database_constraint_with_condition(self):
UniqueConstraintConditionProduct.objects.create(name="p1")
UniqueConstraintConditionProduct.objects.create(name="p2")
UniqueConstraintConditionProduct.objects.create(name="p1", color="blue")
UniqueConstraintConditionProduct.objects.create(name="p2", color="blue")
with self.assertRaises(IntegrityError):
UniqueConstraintConditionProduct.objects.create(name="p1")
UniqueConstraintConditionProduct.objects.create(name="p1", color="blue")

def test_model_validation(self):
msg = "Unique constraint product with this Name and Color already exists."
Expand All @@ -840,13 +840,14 @@ def test_model_validation_with_condition(self):
Model.validate_constraints().
"""
obj1 = UniqueConstraintConditionProduct.objects.create(name="p1", color="red")
obj2 = UniqueConstraintConditionProduct.objects.create(name="p2")
obj2 = UniqueConstraintConditionProduct.objects.create(name="p2", color="blue")
UniqueConstraintConditionProduct(
name=obj1.name, color="blue"
).validate_constraints()
msg = "Constraint “name_without_color_uniq” is violated."
with self.assertRaisesMessage(ValidationError, msg):
UniqueConstraintConditionProduct(name=obj2.name).validate_constraints()
p = UniqueConstraintConditionProduct(name=obj2.name, color="blue")
p.validate_constraints()

def test_model_validation_constraint_no_code_error(self):
class ValidateNoCodeErrorConstraint(UniqueConstraint):
Expand Down Expand Up @@ -917,13 +918,13 @@ def test_validate_fields_unattached(self):

@skipUnlessDBFeature("supports_partial_indexes")
def test_validate_condition(self):
p1 = UniqueConstraintConditionProduct.objects.create(name="p1")
p1 = UniqueConstraintConditionProduct.objects.create(name="p1", color="blue")
constraint = UniqueConstraintConditionProduct._meta.constraints[0]
msg = "Constraint “name_without_color_uniq” is violated."
with self.assertRaisesMessage(ValidationError, msg):
constraint.validate(
UniqueConstraintConditionProduct,
UniqueConstraintConditionProduct(name=p1.name, color=None),
UniqueConstraintConditionProduct(name=p1.name, color="blue"),
)
# Values not matching condition are ignored.
constraint.validate(
Expand All @@ -941,19 +942,19 @@ def test_validate_condition(self):

@skipUnlessDBFeature("supports_partial_indexes")
def test_validate_condition_custom_error(self):
p1 = UniqueConstraintConditionProduct.objects.create(name="p1")
p1 = UniqueConstraintConditionProduct.objects.create(name="p1", color="blue")
constraint = models.UniqueConstraint(
fields=["name"],
name="name_without_color_uniq",
condition=models.Q(color__isnull=True),
condition=models.Q(color="blue"),
violation_error_code="custom_code",
violation_error_message="Custom message",
)
msg = "Custom message"
with self.assertRaisesMessage(ValidationError, msg) as cm:
constraint.validate(
UniqueConstraintConditionProduct,
UniqueConstraintConditionProduct(name=p1.name, color=None),
UniqueConstraintConditionProduct(name=p1.name, color="blue"),
)
self.assertEqual(cm.exception.code, "custom_code")

Expand Down Expand Up @@ -1006,9 +1007,13 @@ def test_validate_expression_condition(self):
constraint = models.UniqueConstraint(
Lower("name"),
name="name_lower_without_color_uniq",
condition=models.Q(color__isnull=True),
condition=models.Q(color="blue"),
)
p2 = UniqueConstraintProduct.objects.create(name="p2", color="blue")
non_unique_product = UniqueConstraintProduct(
name=p2.name.upper(),
color=p2.color,
)
non_unique_product = UniqueConstraintProduct(name=self.p2.name.upper())
msg = "Constraint “name_lower_without_color_uniq” is violated."
with self.assertRaisesMessage(ValidationError, msg):
constraint.validate(UniqueConstraintProduct, non_unique_product)
Expand Down
2 changes: 1 addition & 1 deletion tests/introspection/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class Meta:
models.UniqueConstraint(
fields=["name"],
name="cond_name_without_color_uniq",
condition=models.Q(color__isnull=True),
condition=models.Q(color="blue"),
),
]

Expand Down
2 changes: 1 addition & 1 deletion tests/validation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ class Meta:
models.UniqueConstraint(
fields=["name"],
name="name_without_color_uniq_validation",
condition=models.Q(color__isnull=True),
condition=models.Q(color="blue"),
),
]

Expand Down
8 changes: 4 additions & 4 deletions tests/validation/test_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ def test_full_clean_with_unique_constraints_disabled(self):

@skipUnlessDBFeature("supports_partial_indexes")
def test_full_clean_with_partial_unique_constraints(self):
UniqueConstraintConditionProduct.objects.create(name="product")
product = UniqueConstraintConditionProduct(name="product")
UniqueConstraintConditionProduct.objects.create(name="product", color="blue")
product = UniqueConstraintConditionProduct(name="product", color="blue")
with self.assertRaises(ValidationError) as cm:
product.full_clean()
self.assertEqual(
Expand All @@ -91,8 +91,8 @@ def test_full_clean_with_partial_unique_constraints(self):

@skipUnlessDBFeature("supports_partial_indexes")
def test_full_clean_with_partial_unique_constraints_disabled(self):
UniqueConstraintConditionProduct.objects.create(name="product")
product = UniqueConstraintConditionProduct(name="product")
UniqueConstraintConditionProduct.objects.create(name="product", color="blue")
product = UniqueConstraintConditionProduct(name="product", color="blue")
product.full_clean(validate_constraints=False)

@skipUnlessDBFeature("supports_nulls_distinct_unique_constraints")
Expand Down

0 comments on commit ff43b2b

Please sign in to comment.