Loading django/forms/models.py +25 −15 Original line number Diff line number Diff line Loading @@ -15,6 +15,11 @@ from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput from widgets import media_property from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME try: set except NameError: from sets import Set as set # Python 2.3 fallback __all__ = ( 'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model', 'save_instance', 'form_for_fields', 'ModelChoiceField', Loading Loading @@ -239,6 +244,7 @@ class BaseModelForm(BaseForm): # 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]] bad_fields = set() for unique_check in unique_checks: # Try to look up an existing object with the same values as this # object's values for all the unique field. Loading Loading @@ -279,12 +285,16 @@ class BaseModelForm(BaseForm): '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: 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: # 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) def save(self, commit=True): Loading tests/regressiontests/model_forms_regress/__init__.py 0 → 100644 +0 −0 Empty file added. tests/regressiontests/model_forms_regress/models.py 0 → 100644 +32 −0 Original line number Diff line number Diff line 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 """} Loading
django/forms/models.py +25 −15 Original line number Diff line number Diff line Loading @@ -15,6 +15,11 @@ from widgets import Select, SelectMultiple, HiddenInput, MultipleHiddenInput from widgets import media_property from formsets import BaseFormSet, formset_factory, DELETION_FIELD_NAME try: set except NameError: from sets import Set as set # Python 2.3 fallback __all__ = ( 'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model', 'save_instance', 'form_for_fields', 'ModelChoiceField', Loading Loading @@ -239,6 +244,7 @@ class BaseModelForm(BaseForm): # 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]] bad_fields = set() for unique_check in unique_checks: # Try to look up an existing object with the same values as this # object's values for all the unique field. Loading Loading @@ -279,12 +285,16 @@ class BaseModelForm(BaseForm): '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: 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: # 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) def save(self, commit=True): Loading
tests/regressiontests/model_forms_regress/models.py 0 → 100644 +32 −0 Original line number Diff line number Diff line 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 """}