Ticket #8209: 8209_model_forms_unique.diff

File 8209_model_forms_unique.diff, 3.7 KB (added by dgouldin, 7 years ago)
  • django/forms/models.py

     
    201201        super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
    202202                                            error_class, label_suffix, empty_permitted)
    203203
     204    def clean(self):
     205        unique_checks = self.instance._meta.unique_together[:]
     206        form_errors = []
     207        for name, field in self.fields.items():
     208            if name in self.cleaned_data and self.instance._meta.get_field_by_name(name)[0].unique:
     209                unique_checks.append((name,))
     210        for unique_check in unique_checks:
     211            kwargs = dict([(field_name, self.cleaned_data[field_name]) for field_name in unique_check])
     212            if self.instance._default_manager.filter(**kwargs).exclude(pk=self.instance.id).count() != 0:
     213                model_name = type(self.instance)._meta.verbose_name.title()
     214                if len(unique_check) == 1:
     215                    field_name = unique_check[0]
     216                    field_label = self.fields[field_name].label
     217                    self._errors[field_name] = ErrorList(["%s with this %s already exists." % (model_name, field_label)])
     218                else:
     219                    field_labels = [self.fields[field_name].label for field_name in unique_check]
     220                    form_errors.append("%s with this %s already exists." % (model_name, ' and '.join(field_labels)))
     221                for field_name in unique_check:
     222                    self.cleaned_data.pop(field_name, '')
     223        if form_errors:
     224            raise ValidationError, form_errors
     225        return self.cleaned_data
     226   
    204227    def save(self, commit=True):
    205228        """
    206229        Saves this ``form``'s cleaned_data into model instance
  • tests/modeltests/model_forms/models.py

     
    8383    def __unicode__(self):
    8484        return self.description
    8585
     86class Unique(models.Model):
     87    unique_field = models.CharField(max_length=100, unique=True)
     88
     89class UniqueTogether(models.Model):
     90    unique_field_1 = models.CharField(max_length=100)
     91    unique_field_2 = models.CharField(max_length=100)
     92   
     93    class Meta:
     94        unique_together = (('unique_field_1', 'unique_field_2'),)
     95
     96
    8697__test__ = {'API_TESTS': """
    8798>>> from django import forms
    8899>>> from django.forms.models import ModelForm
     
    10161027<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
    10171028<script type="text/javascript" src="/some/form/javascript"></script>
    10181029
     1030# ModelForm test of unique constraint
     1031
     1032>>> class UniqueForm(ModelForm):
     1033...     class Meta:
     1034...         model = Unique
     1035>>> form1 = UniqueForm({'unique_field': 'unique'})
     1036>>> form1.is_valid()
     1037True
     1038>>> form1.save()
     1039<Unique: Unique object>
     1040>>> form2 = UniqueForm({'unique_field': 'unique'})
     1041>>> form2.is_valid()
     1042False
     1043>>> form2._errors
     1044{'unique_field': [u'Unique with this Unique field already exists.']}
     1045
     1046# ModelForm test of unique_together constraint
     1047
     1048>>> class UniqueTogetherForm(ModelForm):
     1049...     class Meta:
     1050...         model = UniqueTogether
     1051>>> form1 = UniqueTogetherForm({'unique_field_1': 'unique1', 'unique_field_2': 'unique2'})
     1052>>> form1.is_valid()
     1053True
     1054>>> form1.save()
     1055<UniqueTogether: UniqueTogether object>
     1056>>> form2 = UniqueTogetherForm({'unique_field_1': 'unique1', 'unique_field_2': 'unique2'})
     1057>>> form2.is_valid()
     1058False
     1059>>> form2._errors
     1060{'__all__': [u'Unique Together with this Unique field 1 and Unique field 2 already exists.']}
     1061
    10191062"""}
Back to Top