Fixed #9493 -- Corrected error handling of formsets that violate unique constraints across the component forms. Thanks to Alex Gaynor for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10682 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2009-05-07 12:17:52 +00:00
parent eb81d5acb3
commit f259494f82
3 changed files with 316 additions and 51 deletions

View file

@ -23,6 +23,12 @@ class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100)
class Meta:
unique_together = (
('author', 'title'),
)
ordering = ['id']
def __unicode__(self):
return self.title
@ -58,7 +64,7 @@ class CustomPrimaryKey(models.Model):
class Place(models.Model):
name = models.CharField(max_length=50)
city = models.CharField(max_length=50)
def __unicode__(self):
return self.name
@ -85,7 +91,7 @@ class OwnerProfile(models.Model):
class Restaurant(Place):
serves_pizza = models.BooleanField()
def __unicode__(self):
return self.name
@ -166,6 +172,15 @@ class Poem(models.Model):
def __unicode__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=50, unique_for_date='posted', blank=True)
slug = models.CharField(max_length=50, unique_for_year='posted', blank=True)
subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True)
posted = models.DateField()
def __unicode__(self):
return self.name
__test__ = {'API_TESTS': """
>>> from datetime import date
@ -573,7 +588,7 @@ True
... print book.title
Les Fleurs du Mal
Test inline formsets where the inline-edited object uses multi-table inheritance, thus
Test inline formsets where the inline-edited object uses multi-table inheritance, thus
has a non AutoField yet auto-created primary key.
>>> AuthorBooksFormSet3 = inlineformset_factory(Author, AlternateBook, can_delete=False, extra=1)
@ -740,7 +755,7 @@ True
>>> formset.save()
[<OwnerProfile: Joe Perry is 55>]
# ForeignKey with unique=True should enforce max_num=1
# ForeignKey with unique=True should enforce max_num=1
>>> FormSet = inlineformset_factory(Place, Location, can_delete=False)
>>> formset = FormSet(instance=place)
@ -943,4 +958,129 @@ True
>>> FormSet = modelformset_factory(ClassyMexicanRestaurant, fields=["tacos_are_yummy"])
>>> sorted(FormSet().forms[0].fields.keys())
['restaurant', 'tacos_are_yummy']
# Prevent duplicates from within the same formset
>>> FormSet = modelformset_factory(Product, extra=2)
>>> data = {
... 'form-TOTAL_FORMS': 2,
... 'form-INITIAL_FORMS': 0,
... 'form-0-slug': 'red_car',
... 'form-1-slug': 'red_car',
... }
>>> formset = FormSet(data)
>>> formset.is_valid()
False
>>> formset._non_form_errors
[u'Please correct the duplicate data for slug.']
>>> FormSet = modelformset_factory(Price, extra=2)
>>> data = {
... 'form-TOTAL_FORMS': 2,
... 'form-INITIAL_FORMS': 0,
... 'form-0-price': '25',
... 'form-0-quantity': '7',
... 'form-1-price': '25',
... 'form-1-quantity': '7',
... }
>>> formset = FormSet(data)
>>> formset.is_valid()
False
>>> formset._non_form_errors
[u'Please correct the duplicate data for price and quantity, which must be unique.']
# only the price field is specified, this should skip any unique checks since the unique_together is not fulfilled.
# this will fail with a KeyError if broken.
>>> FormSet = modelformset_factory(Price, fields=("price",), extra=2)
>>> data = {
... 'form-TOTAL_FORMS': '2',
... 'form-INITIAL_FORMS': '0',
... 'form-0-price': '24',
... 'form-1-price': '24',
... }
>>> formset = FormSet(data)
>>> formset.is_valid()
True
>>> FormSet = inlineformset_factory(Author, Book, extra=0)
>>> author = Author.objects.order_by('id')[0]
>>> book_ids = author.book_set.values_list('id', flat=True)
>>> data = {
... 'book_set-TOTAL_FORMS': '2',
... 'book_set-INITIAL_FORMS': '2',
...
... 'book_set-0-title': 'The 2008 Election',
... 'book_set-0-author': str(author.id),
... 'book_set-0-id': str(book_ids[0]),
...
... 'book_set-1-title': 'The 2008 Election',
... 'book_set-1-author': str(author.id),
... 'book_set-1-id': str(book_ids[1]),
... }
>>> formset = FormSet(data=data, instance=author)
>>> formset.is_valid()
False
>>> formset._non_form_errors
[u'Please correct the duplicate data for title.']
>>> formset.errors
[{}, {'__all__': u'Please correct the duplicate values below.'}]
>>> FormSet = modelformset_factory(Post, extra=2)
>>> data = {
... 'form-TOTAL_FORMS': '2',
... 'form-INITIAL_FORMS': '0',
...
... 'form-0-title': 'blah',
... 'form-0-slug': 'Morning',
... 'form-0-subtitle': 'foo',
... 'form-0-posted': '2009-01-01',
... 'form-1-title': 'blah',
... 'form-1-slug': 'Morning in Prague',
... 'form-1-subtitle': 'rawr',
... 'form-1-posted': '2009-01-01'
... }
>>> formset = FormSet(data)
>>> formset.is_valid()
False
>>> formset._non_form_errors
[u'Please correct the duplicate data for title which must be unique for the date in posted.']
>>> formset.errors
[{}, {'__all__': u'Please correct the duplicate values below.'}]
>>> data = {
... 'form-TOTAL_FORMS': '2',
... 'form-INITIAL_FORMS': '0',
...
... 'form-0-title': 'foo',
... 'form-0-slug': 'Morning in Prague',
... 'form-0-subtitle': 'foo',
... 'form-0-posted': '2009-01-01',
... 'form-1-title': 'blah',
... 'form-1-slug': 'Morning in Prague',
... 'form-1-subtitle': 'rawr',
... 'form-1-posted': '2009-08-02'
... }
>>> formset = FormSet(data)
>>> formset.is_valid()
False
>>> formset._non_form_errors
[u'Please correct the duplicate data for slug which must be unique for the year in posted.']
>>> data = {
... 'form-TOTAL_FORMS': '2',
... 'form-INITIAL_FORMS': '0',
...
... 'form-0-title': 'foo',
... 'form-0-slug': 'Morning in Prague',
... 'form-0-subtitle': 'rawr',
... 'form-0-posted': '2008-08-01',
... 'form-1-title': 'blah',
... 'form-1-slug': 'Prague',
... 'form-1-subtitle': 'rawr',
... 'form-1-posted': '2009-08-02'
... }
>>> formset = FormSet(data)
>>> formset.is_valid()
False
>>> formset._non_form_errors
[u'Please correct the duplicate data for subtitle which must be unique for the month in posted.']
"""}