mirror of
				https://github.com/django/django.git
				synced 2025-10-28 16:16:12 +00:00 
			
		
		
		
	[5.1.x] Refs #30581 -- Made unattached UniqueConstraint(fields) validation testable.
The logic allowing UniqueConstraint(fields).validate to preserve backward
compatiblity with Model.unique_error_message failed to account for cases where
the constraint might not be attached to a model which is a common pattern
during testing.
This changes allows for arbitrary UniqueConstraint(fields) to be tested in
isolation without requiring actual models backing them up.
Co-authored-by: Mark G <mark.gensler@protonmail.com>
Backport of 13922580cc from main.
			
			
This commit is contained in:
		
				
					committed by
					
						 Sarah Boyce
						Sarah Boyce
					
				
			
			
				
	
			
			
			
						parent
						
							df7ebb8b02
						
					
				
				
					commit
					a2791f5ea2
				
			| @@ -653,19 +653,16 @@ class UniqueConstraint(BaseConstraint): | |||||||
|             queryset = queryset.exclude(pk=model_class_pk) |             queryset = queryset.exclude(pk=model_class_pk) | ||||||
|         if not self.condition: |         if not self.condition: | ||||||
|             if queryset.exists(): |             if queryset.exists(): | ||||||
|                 if self.expressions: |                 if self.fields: | ||||||
|  |                     # When fields are defined, use the unique_error_message() for | ||||||
|  |                     # backward compatibility. | ||||||
|                     raise ValidationError( |                     raise ValidationError( | ||||||
|                         self.get_violation_error_message(), |                         instance.unique_error_message(model, self.fields), | ||||||
|                         code=self.violation_error_code, |  | ||||||
|                     ) |                     ) | ||||||
|                 # When fields are defined, use the unique_error_message() for |                 raise ValidationError( | ||||||
|                 # backward compatibility. |                     self.get_violation_error_message(), | ||||||
|                 for model, constraints in instance.get_constraints(): |                     code=self.violation_error_code, | ||||||
|                     for constraint in constraints: |                 ) | ||||||
|                         if constraint is self: |  | ||||||
|                             raise ValidationError( |  | ||||||
|                                 instance.unique_error_message(model, self.fields), |  | ||||||
|                             ) |  | ||||||
|         else: |         else: | ||||||
|             against = instance._get_field_value_map(meta=model._meta, exclude=exclude) |             against = instance._get_field_value_map(meta=model._meta, exclude=exclude) | ||||||
|             try: |             try: | ||||||
|   | |||||||
| @@ -896,6 +896,13 @@ class UniqueConstraintTests(TestCase): | |||||||
|                 ChildUniqueConstraintProduct(name=self.p1.name, color=self.p1.color), |                 ChildUniqueConstraintProduct(name=self.p1.name, color=self.p1.color), | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|  |     def test_validate_fields_unattached(self): | ||||||
|  |         Product.objects.create(price=42) | ||||||
|  |         constraint = models.UniqueConstraint(fields=["price"], name="uniq_prices") | ||||||
|  |         msg = "Product with this Price already exists." | ||||||
|  |         with self.assertRaisesMessage(ValidationError, msg): | ||||||
|  |             constraint.validate(Product, Product(price=42)) | ||||||
|  |  | ||||||
|     @skipUnlessDBFeature("supports_partial_indexes") |     @skipUnlessDBFeature("supports_partial_indexes") | ||||||
|     def test_validate_condition(self): |     def test_validate_condition(self): | ||||||
|         p1 = UniqueConstraintConditionProduct.objects.create(name="p1") |         p1 = UniqueConstraintConditionProduct.objects.create(name="p1") | ||||||
| @@ -921,7 +928,7 @@ class UniqueConstraintTests(TestCase): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     @skipUnlessDBFeature("supports_partial_indexes") |     @skipUnlessDBFeature("supports_partial_indexes") | ||||||
|     def test_validate_conditon_custom_error(self): |     def test_validate_condition_custom_error(self): | ||||||
|         p1 = UniqueConstraintConditionProduct.objects.create(name="p1") |         p1 = UniqueConstraintConditionProduct.objects.create(name="p1") | ||||||
|         constraint = models.UniqueConstraint( |         constraint = models.UniqueConstraint( | ||||||
|             fields=["name"], |             fields=["name"], | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user