Ticket #9493: formset-unique.4.diff
File formset-unique.4.diff, 4.5 KB (added by , 16 years ago) |
---|
-
django/forms/models.py
diff --git a/django/forms/models.py b/django/forms/models.py index 99f7ef5..fedbab7 100644
a b class BaseModelFormSet(BaseFormSet): 377 377 form.save_m2m() 378 378 self.save_m2m = save_m2m 379 379 return self.save_existing_objects(commit) + self.save_new_objects(commit) 380 381 def clean(self): 382 self.validate_unique() 383 384 def validate_unique(self): 385 from django.db.models.fields import FieldDoesNotExist 386 unique_checks = [] 387 for name, field in self.forms[0].fields.iteritems(): 388 try: 389 f = self.forms[0].instance._meta.get_field_by_name(name)[0] 390 except FieldDoesNotExist: 391 continue 392 if f.unique: 393 unique_checks.append((name,)) 394 unique_together = self.forms[0].instance._meta.unique_together 395 unique_together = [check for check in unique_together if [True for field in check if field in self.forms[0].fields]] 396 unique_checks.extend(unique_together) 397 398 errors = [] 399 for unique_check in unique_checks: 400 data = set() 401 for i in xrange(self._total_form_count): 402 form = self.forms[i] 403 if not hasattr(form, 'cleaned_data'): 404 continue 405 if [True for field in unique_check if field in form.cleaned_data and form.cleaned_data[field] is not None]: 406 instance = tuple([form.cleaned_data[field] for field in unique_check]) 407 if instance in data: 408 if len(unique_check) == 1: 409 errors.append(_("You have entered duplicate data for %(field)s, all %(field)ss should be unique.") % { 410 'field': unique_check[0], 411 }) 412 else: 413 errors.append(_("You have entered duplicate data for %(field)s, %(field)s should be unique together.") % { 414 'field': get_text_list(unique_check, _("and")), 415 }) 416 break 417 else: 418 data.add(instance) 419 420 if errors: 421 raise ValidationError(errors) 380 422 381 423 def save_existing_objects(self, commit=True): 382 424 self.changed_objects = [] -
docs/topics/forms/modelforms.txt
diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt index ad3fe02..f2875ff 100644
a b in a view. The only difference is that we call ``formset.save()`` to save the 538 538 data into the database. This is described above in 539 539 :ref:`saving-objects-in-the-formset`. 540 540 541 Overiding ``clean()`` on a ``model_formset`` 542 -------------------------------------------- 543 544 Just like with ``ModelForms``, by default the ``clean()`` method of a 545 ``model_formset`` will validate that none of the items in the formset validate 546 the unique constraints on your model(either unique or unique_together). If you 547 want to overide the ``clean()`` method on a ``model_formset`` and maintain this 548 validation, you must call the parent classes ``clean`` method. 549 550 541 551 Using ``inlineformset_factory`` 542 552 ------------------------------- 543 553 -
tests/modeltests/model_formsets/models.py
diff --git a/tests/modeltests/model_formsets/models.py b/tests/modeltests/model_formsets/models.py index 8e28e6f..57ecf7d 100644
a b True 792 792 >>> formset.get_queryset() 793 793 [<Player: Bobby>] 794 794 795 # Prevent duplicates from within the same formset 796 >>> FormSet = modelformset_factory(Product, extra=2) 797 >>> data = { 798 ... 'form-TOTAL_FORMS': 2, 799 ... 'form-INITIAL_FORMS': 0, 800 ... 'form-0-slug': 'red_car', 801 ... 'form-1-slug': 'red_car', 802 ... } 803 >>> formset = FormSet(data) 804 >>> formset.is_valid() 805 False 806 >>> formset._non_form_errors 807 [u'You have entered duplicate data for slug, all slugs should be unique.'] 808 809 >>> FormSet = modelformset_factory(Price, extra=2) 810 >>> data = { 811 ... 'form-TOTAL_FORMS': 2, 812 ... 'form-INITIAL_FORMS': 0, 813 ... 'form-0-price': '25', 814 ... 'form-0-quantity': '7', 815 ... 'form-1-price': '25', 816 ... 'form-1-quantity': '7', 817 ... } 818 >>> formset = FormSet(data) 819 >>> formset.is_valid() 820 False 821 >>> formset._non_form_errors 822 [u'You have entered duplicate data for price and quantity, price and quantity should be unique together.'] 795 823 """}