mirror of
				https://github.com/django/django.git
				synced 2025-10-26 07:06:08 +00:00 
			
		
		
		
	[1.0.X] Fixed #9319 -- Fixed a crash when using the same model field in multiple
unique_together constraints. Backport of r9208 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9209 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -15,6 +15,11 @@ from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput | |||||||
| from widgets import media_property | from widgets import media_property | ||||||
| from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME | from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME | ||||||
|  |  | ||||||
|  | try: | ||||||
|  |     set | ||||||
|  | except NameError: | ||||||
|  |     from sets import Set as set     # Python 2.3 fallback | ||||||
|  |  | ||||||
| __all__ = ( | __all__ = ( | ||||||
|     'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model', |     'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model', | ||||||
|     'save_instance', 'form_for_fields', 'ModelChoiceField', |     'save_instance', 'form_for_fields', 'ModelChoiceField', | ||||||
| @@ -239,6 +244,7 @@ class BaseModelForm(BaseForm): | |||||||
|         # Don't run unique checks on fields that already have an error. |         # Don't run unique checks on fields that already have an error. | ||||||
|         unique_checks = [check for check in unique_checks if not [x in self._errors for x in check if x in self._errors]] |         unique_checks = [check for check in unique_checks if not [x in self._errors for x in check if x in self._errors]] | ||||||
|  |  | ||||||
|  |         bad_fields = set() | ||||||
|         for unique_check in unique_checks: |         for unique_check in unique_checks: | ||||||
|             # Try to look up an existing object with the same values as this |             # Try to look up an existing object with the same values as this | ||||||
|             # object's values for all the unique field. |             # object's values for all the unique field. | ||||||
| @@ -279,12 +285,16 @@ class BaseModelForm(BaseForm): | |||||||
|                          'field_label': unicode(field_labels)} |                          'field_label': unicode(field_labels)} | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|                 # Remove the data from the cleaned_data dict since it was invalid |                 # Mark these fields as needing to be removed from cleaned data | ||||||
|  |                 # later. | ||||||
|                 for field_name in unique_check: |                 for field_name in unique_check: | ||||||
|                     del self.cleaned_data[field_name] |                     bad_fields.add(field_name) | ||||||
|  |  | ||||||
|  |         for field_name in bad_fields: | ||||||
|  |             del self.cleaned_data[field_name] | ||||||
|         if form_errors: |         if form_errors: | ||||||
|             # Raise the unique together errors since they are considered form-wide. |             # Raise the unique together errors since they are considered | ||||||
|  |             # form-wide. | ||||||
|             raise ValidationError(form_errors) |             raise ValidationError(form_errors) | ||||||
|  |  | ||||||
|     def save(self, commit=True): |     def save(self, commit=True): | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								tests/regressiontests/model_forms_regress/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								tests/regressiontests/model_forms_regress/models.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | from django.db import models | ||||||
|  | from django import forms | ||||||
|  |  | ||||||
|  | class Triple(models.Model): | ||||||
|  |     left = models.IntegerField() | ||||||
|  |     middle = models.IntegerField() | ||||||
|  |     right = models.IntegerField() | ||||||
|  |  | ||||||
|  |     def __unicode__(self): | ||||||
|  |         return u"%d, %d, %d" % (self.left, self.middle, self.right) | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         unique_together = (('left', 'middle'), ('middle', 'right')) | ||||||
|  |  | ||||||
|  | __test__ = {'API_TESTS': """ | ||||||
|  | When the same field is involved in multiple unique_together constraints, we | ||||||
|  | need to make sure we don't remove the data for it before doing all the | ||||||
|  | validation checking (not just failing after the first one). | ||||||
|  |  | ||||||
|  | >>> _ = Triple.objects.create(left=1, middle=2, right=3) | ||||||
|  | >>> class TripleForm(forms.ModelForm): | ||||||
|  | ...     class Meta: | ||||||
|  | ...         model = Triple | ||||||
|  |  | ||||||
|  | >>> form = TripleForm({'left': '1', 'middle': '2', 'right': '3'}) | ||||||
|  | >>> form.is_valid() | ||||||
|  | False | ||||||
|  | >>> form = TripleForm({'left': '1', 'middle': '3', 'right': '1'}) | ||||||
|  | >>> form.is_valid() | ||||||
|  | True | ||||||
|  | """} | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user