mirror of https://github.com/django/django.git
Fixed #12881: Corrected handling of inherited unique constraints. Thanks for report fgaudin.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12797 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
883329ecb3
commit
47a822207f
|
@ -707,37 +707,50 @@ class Model(object):
|
|||
if exclude is None:
|
||||
exclude = []
|
||||
unique_checks = []
|
||||
for check in self._meta.unique_together:
|
||||
for name in check:
|
||||
# If this is an excluded field, don't add this check.
|
||||
if name in exclude:
|
||||
break
|
||||
else:
|
||||
unique_checks.append(tuple(check))
|
||||
|
||||
unique_togethers = [(self.__class__, self._meta.unique_together)]
|
||||
for parent_class in self._meta.parents.keys():
|
||||
if parent_class._meta.unique_together:
|
||||
unique_togethers.append((parent_class, parent_class._meta.unique_together))
|
||||
|
||||
for model_class, unique_together in unique_togethers:
|
||||
for check in unique_together:
|
||||
for name in check:
|
||||
# If this is an excluded field, don't add this check.
|
||||
if name in exclude:
|
||||
break
|
||||
else:
|
||||
unique_checks.append((model_class, tuple(check)))
|
||||
|
||||
# These are checks for the unique_for_<date/year/month>.
|
||||
date_checks = []
|
||||
|
||||
# Gather a list of checks for fields declared as unique and add them to
|
||||
# the list of checks.
|
||||
for f in self._meta.fields:
|
||||
name = f.name
|
||||
if name in exclude:
|
||||
continue
|
||||
if f.unique:
|
||||
unique_checks.append((name,))
|
||||
if f.unique_for_date:
|
||||
date_checks.append(('date', name, f.unique_for_date))
|
||||
if f.unique_for_year:
|
||||
date_checks.append(('year', name, f.unique_for_year))
|
||||
if f.unique_for_month:
|
||||
date_checks.append(('month', name, f.unique_for_month))
|
||||
|
||||
fields_with_class = [(self.__class__, self._meta.local_fields)]
|
||||
for parent_class in self._meta.parents.keys():
|
||||
fields_with_class.append((parent_class, parent_class._meta.local_fields))
|
||||
|
||||
for model_class, fields in fields_with_class:
|
||||
for f in fields:
|
||||
name = f.name
|
||||
if name in exclude:
|
||||
continue
|
||||
if f.unique:
|
||||
unique_checks.append((model_class, (name,)))
|
||||
if f.unique_for_date:
|
||||
date_checks.append((model_class, 'date', name, f.unique_for_date))
|
||||
if f.unique_for_year:
|
||||
date_checks.append((model_class, 'year', name, f.unique_for_year))
|
||||
if f.unique_for_month:
|
||||
date_checks.append((model_class, 'month', name, f.unique_for_month))
|
||||
return unique_checks, date_checks
|
||||
|
||||
def _perform_unique_checks(self, unique_checks):
|
||||
errors = {}
|
||||
|
||||
for unique_check in unique_checks:
|
||||
for model_class, 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.
|
||||
|
||||
|
@ -757,7 +770,7 @@ class Model(object):
|
|||
if len(unique_check) != len(lookup_kwargs.keys()):
|
||||
continue
|
||||
|
||||
qs = self.__class__._default_manager.filter(**lookup_kwargs)
|
||||
qs = model_class._default_manager.filter(**lookup_kwargs)
|
||||
|
||||
# Exclude the current object from the query if we are editing an
|
||||
# instance (as opposed to creating a new one)
|
||||
|
@ -769,13 +782,13 @@ class Model(object):
|
|||
key = unique_check[0]
|
||||
else:
|
||||
key = NON_FIELD_ERRORS
|
||||
errors.setdefault(key, []).append(self.unique_error_message(unique_check))
|
||||
errors.setdefault(key, []).append(self.unique_error_message(model_class, unique_check))
|
||||
|
||||
return errors
|
||||
|
||||
def _perform_date_checks(self, date_checks):
|
||||
errors = {}
|
||||
for lookup_type, field, unique_for in date_checks:
|
||||
for model_class, lookup_type, field, unique_for in date_checks:
|
||||
lookup_kwargs = {}
|
||||
# there's a ticket to add a date lookup, we can remove this special
|
||||
# case if that makes it's way in
|
||||
|
@ -788,7 +801,7 @@ class Model(object):
|
|||
lookup_kwargs['%s__%s' % (unique_for, lookup_type)] = getattr(date, lookup_type)
|
||||
lookup_kwargs[field] = getattr(self, field)
|
||||
|
||||
qs = self.__class__._default_manager.filter(**lookup_kwargs)
|
||||
qs = model_class._default_manager.filter(**lookup_kwargs)
|
||||
# Exclude the current object from the query if we are editing an
|
||||
# instance (as opposed to creating a new one)
|
||||
if not getattr(self, '_adding', False) and self.pk is not None:
|
||||
|
@ -808,8 +821,8 @@ class Model(object):
|
|||
'lookup': lookup_type,
|
||||
}
|
||||
|
||||
def unique_error_message(self, unique_check):
|
||||
opts = self._meta
|
||||
def unique_error_message(self, model_class, unique_check):
|
||||
opts = model_class._meta
|
||||
model_name = capfirst(opts.verbose_name)
|
||||
|
||||
# A unique field
|
||||
|
|
|
@ -488,7 +488,7 @@ class BaseModelFormSet(BaseFormSet):
|
|||
|
||||
errors = []
|
||||
# Do each of the unique checks (unique and unique_together)
|
||||
for unique_check in all_unique_checks:
|
||||
for uclass, unique_check in all_unique_checks:
|
||||
seen_data = set()
|
||||
for form in self.forms:
|
||||
# if the form doesn't have cleaned_data then we ignore it,
|
||||
|
@ -512,7 +512,7 @@ class BaseModelFormSet(BaseFormSet):
|
|||
# iterate over each of the date checks now
|
||||
for date_check in all_date_checks:
|
||||
seen_data = set()
|
||||
lookup, field, unique_for = date_check
|
||||
uclass, lookup, field, unique_for = date_check
|
||||
for form in self.forms:
|
||||
# if the form doesn't have cleaned_data then we ignore it,
|
||||
# it's already invalid
|
||||
|
@ -556,9 +556,9 @@ class BaseModelFormSet(BaseFormSet):
|
|||
def get_date_error_message(self, date_check):
|
||||
return ugettext("Please correct the duplicate data for %(field_name)s "
|
||||
"which must be unique for the %(lookup)s in %(date_field)s.") % {
|
||||
'field_name': date_check[1],
|
||||
'date_field': date_check[2],
|
||||
'lookup': unicode(date_check[0]),
|
||||
'field_name': date_check[2],
|
||||
'date_field': date_check[3],
|
||||
'lookup': unicode(date_check[1]),
|
||||
}
|
||||
|
||||
def get_form_error(self):
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
from django.forms import ModelForm
|
||||
|
||||
from models import Product, Price, Book, DerivedBook, ExplicitPK, Post, DerivedPost
|
||||
|
||||
class ProductForm(ModelForm):
|
||||
class Meta:
|
||||
model = Product
|
||||
|
||||
class PriceForm(ModelForm):
|
||||
class Meta:
|
||||
model = Price
|
||||
|
||||
class BookForm(ModelForm):
|
||||
class Meta:
|
||||
model = Book
|
||||
|
||||
class DerivedBookForm(ModelForm):
|
||||
class Meta:
|
||||
model = DerivedBook
|
||||
|
||||
class ExplicitPKForm(ModelForm):
|
||||
class Meta:
|
||||
model = ExplicitPK
|
||||
fields = ('key', 'desc',)
|
||||
|
||||
class PostForm(ModelForm):
|
||||
class Meta:
|
||||
model = Post
|
||||
|
||||
class DerivedPostForm(ModelForm):
|
||||
class Meta:
|
||||
model = DerivedPost
|
|
@ -101,7 +101,7 @@ try:
|
|||
from PIL import Image, _imaging
|
||||
except ImportError:
|
||||
import Image, _imaging
|
||||
|
||||
|
||||
test_images = True
|
||||
|
||||
class ImageFile(models.Model):
|
||||
|
@ -181,6 +181,18 @@ class Book(models.Model):
|
|||
class Meta:
|
||||
unique_together = ('title', 'author')
|
||||
|
||||
class BookXtra(models.Model):
|
||||
isbn = models.CharField(max_length=16, unique=True)
|
||||
suffix1 = models.IntegerField(blank=True, default=0)
|
||||
suffix2 = models.IntegerField(blank=True, default=0)
|
||||
|
||||
class Meta:
|
||||
unique_together = (('suffix1', 'suffix2'))
|
||||
abstract = True
|
||||
|
||||
class DerivedBook(Book, BookXtra):
|
||||
pass
|
||||
|
||||
class ExplicitPK(models.Model):
|
||||
key = models.CharField(max_length=20, primary_key=True)
|
||||
desc = models.CharField(max_length=20, blank=True, unique=True)
|
||||
|
@ -199,6 +211,9 @@ class Post(models.Model):
|
|||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class DerivedPost(Post):
|
||||
pass
|
||||
|
||||
class BigInt(models.Model):
|
||||
biggie = models.BigIntegerField()
|
||||
|
||||
|
@ -1424,41 +1439,6 @@ True
|
|||
>>> f.cleaned_data
|
||||
{'field': u'1'}
|
||||
|
||||
# unique/unique_together validation
|
||||
|
||||
>>> class ProductForm(ModelForm):
|
||||
... class Meta:
|
||||
... model = Product
|
||||
>>> form = ProductForm({'slug': 'teddy-bear-blue'})
|
||||
>>> form.is_valid()
|
||||
True
|
||||
>>> obj = form.save()
|
||||
>>> obj
|
||||
<Product: teddy-bear-blue>
|
||||
>>> form = ProductForm({'slug': 'teddy-bear-blue'})
|
||||
>>> form.is_valid()
|
||||
False
|
||||
>>> form._errors
|
||||
{'slug': [u'Product with this Slug already exists.']}
|
||||
>>> form = ProductForm({'slug': 'teddy-bear-blue'}, instance=obj)
|
||||
>>> form.is_valid()
|
||||
True
|
||||
|
||||
# ModelForm test of unique_together constraint
|
||||
>>> class PriceForm(ModelForm):
|
||||
... class Meta:
|
||||
... model = Price
|
||||
>>> form = PriceForm({'price': '6.00', 'quantity': '1'})
|
||||
>>> form.is_valid()
|
||||
True
|
||||
>>> form.save()
|
||||
<Price: 1 for 6.00>
|
||||
>>> form = PriceForm({'price': '6.00', 'quantity': '1'})
|
||||
>>> form.is_valid()
|
||||
False
|
||||
>>> form._errors
|
||||
{'__all__': [u'Price with this Price and Quantity already exists.']}
|
||||
|
||||
This Price instance generated by this form is not valid because the quantity
|
||||
field is required, but the form is valid because the field is excluded from
|
||||
the form. This is for backwards compatibility.
|
||||
|
@ -1495,51 +1475,6 @@ True
|
|||
>>> form.instance.pk is None
|
||||
True
|
||||
|
||||
# Unique & unique together with null values
|
||||
>>> class BookForm(ModelForm):
|
||||
... class Meta:
|
||||
... model = Book
|
||||
>>> w = Writer.objects.get(name='Mike Royko')
|
||||
>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It', 'author' : w.pk})
|
||||
>>> form.is_valid()
|
||||
True
|
||||
>>> form.save()
|
||||
<Book: Book object>
|
||||
>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It', 'author' : w.pk})
|
||||
>>> form.is_valid()
|
||||
False
|
||||
>>> form._errors
|
||||
{'__all__': [u'Book with this Title and Author already exists.']}
|
||||
>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It'})
|
||||
>>> form.is_valid()
|
||||
True
|
||||
>>> form.save()
|
||||
<Book: Book object>
|
||||
>>> form = BookForm({'title': 'I May Be Wrong But I Doubt It'})
|
||||
>>> form.is_valid()
|
||||
True
|
||||
|
||||
# Test for primary_key being in the form and failing validation.
|
||||
>>> class ExplicitPKForm(ModelForm):
|
||||
... class Meta:
|
||||
... model = ExplicitPK
|
||||
... fields = ('key', 'desc',)
|
||||
>>> form = ExplicitPKForm({'key': u'', 'desc': u'' })
|
||||
>>> form.is_valid()
|
||||
False
|
||||
|
||||
# Ensure keys and blank character strings are tested for uniqueness.
|
||||
>>> form = ExplicitPKForm({'key': u'key1', 'desc': u''})
|
||||
>>> form.is_valid()
|
||||
True
|
||||
>>> form.save()
|
||||
<ExplicitPK: key1>
|
||||
>>> form = ExplicitPKForm({'key': u'key1', 'desc': u''})
|
||||
>>> form.is_valid()
|
||||
False
|
||||
>>> sorted(form.errors.items())
|
||||
[('__all__', [u'Explicit pk with this Key and Desc already exists.']), ('desc', [u'Explicit pk with this Desc already exists.']), ('key', [u'Explicit pk with this Key already exists.'])]
|
||||
|
||||
# Choices on CharField and IntegerField
|
||||
>>> class ArticleForm(ModelForm):
|
||||
... class Meta:
|
||||
|
@ -1605,38 +1540,6 @@ ValidationError: [u'Select a valid choice. z is not one of the available choices
|
|||
<tr><th><label for="id_description">Description:</label></th><td><input type="text" name="description" id="id_description" /></td></tr>
|
||||
<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
|
||||
|
||||
### Validation on unique_for_date
|
||||
|
||||
>>> p = Post.objects.create(title="Django 1.0 is released", slug="Django 1.0", subtitle="Finally", posted=datetime.date(2008, 9, 3))
|
||||
>>> class PostForm(ModelForm):
|
||||
... class Meta:
|
||||
... model = Post
|
||||
|
||||
>>> f = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-03'})
|
||||
>>> f.is_valid()
|
||||
False
|
||||
>>> f.errors
|
||||
{'title': [u'Title must be unique for Posted date.']}
|
||||
>>> f = PostForm({'title': "Work on Django 1.1 begins", 'posted': '2008-09-03'})
|
||||
>>> f.is_valid()
|
||||
True
|
||||
>>> f = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-04'})
|
||||
>>> f.is_valid()
|
||||
True
|
||||
>>> f = PostForm({'slug': "Django 1.0", 'posted': '2008-01-01'})
|
||||
>>> f.is_valid()
|
||||
False
|
||||
>>> f.errors
|
||||
{'slug': [u'Slug must be unique for Posted year.']}
|
||||
>>> f = PostForm({'subtitle': "Finally", 'posted': '2008-09-30'})
|
||||
>>> f.is_valid()
|
||||
False
|
||||
>>> f.errors
|
||||
{'subtitle': [u'Subtitle must be unique for Posted month.']}
|
||||
>>> f = PostForm({'subtitle': "Finally", "title": "Django 1.0 is released", "slug": "Django 1.0", 'posted': '2008-09-03'}, instance=p)
|
||||
>>> f.is_valid()
|
||||
True
|
||||
|
||||
# Clean up
|
||||
>>> import shutil
|
||||
>>> shutil.rmtree(temp_storage_dir)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import datetime
|
||||
from django.test import TestCase
|
||||
from django import forms
|
||||
from models import Category
|
||||
from models import Category, Writer, Book, DerivedBook, Post
|
||||
from mforms import ProductForm, PriceForm, BookForm, DerivedBookForm, ExplicitPKForm, PostForm, DerivedPostForm
|
||||
|
||||
|
||||
class IncompleteCategoryFormWithFields(forms.ModelForm):
|
||||
|
@ -35,3 +37,140 @@ class ValidationTest(TestCase):
|
|||
form = IncompleteCategoryFormWithExclude(data={'name': 'some name', 'slug': 'some-slug'})
|
||||
assert form.is_valid()
|
||||
|
||||
# unique/unique_together validation
|
||||
class UniqueTest(TestCase):
|
||||
def setUp(self):
|
||||
self.writer = Writer.objects.create(name='Mike Royko')
|
||||
|
||||
def test_simple_unique(self):
|
||||
form = ProductForm({'slug': 'teddy-bear-blue'})
|
||||
self.assertTrue(form.is_valid())
|
||||
obj = form.save()
|
||||
form = ProductForm({'slug': 'teddy-bear-blue'})
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['slug'], [u'Product with this Slug already exists.'])
|
||||
form = ProductForm({'slug': 'teddy-bear-blue'}, instance=obj)
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
def test_unique_together(self):
|
||||
"""ModelForm test of unique_together constraint"""
|
||||
form = PriceForm({'price': '6.00', 'quantity': '1'})
|
||||
self.assertTrue(form.is_valid())
|
||||
form.save()
|
||||
form = PriceForm({'price': '6.00', 'quantity': '1'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['__all__'], [u'Price with this Price and Quantity already exists.'])
|
||||
|
||||
def test_unique_null(self):
|
||||
title = 'I May Be Wrong But I Doubt It'
|
||||
form = BookForm({'title': title, 'author': self.writer.pk})
|
||||
self.assertTrue(form.is_valid())
|
||||
form.save()
|
||||
form = BookForm({'title': title, 'author': self.writer.pk})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['__all__'], [u'Book with this Title and Author already exists.'])
|
||||
form = BookForm({'title': title})
|
||||
self.assertTrue(form.is_valid())
|
||||
form.save()
|
||||
form = BookForm({'title': title})
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
def test_inherited_unique(self):
|
||||
title = 'Boss'
|
||||
Book.objects.create(title=title, author=self.writer, special_id=1)
|
||||
form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'special_id': u'1', 'isbn': '12345'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['special_id'], [u'Book with this Special id already exists.'])
|
||||
|
||||
def test_inherited_unique_together(self):
|
||||
title = 'Boss'
|
||||
form = BookForm({'title': title, 'author': self.writer.pk})
|
||||
self.assertTrue(form.is_valid())
|
||||
form.save()
|
||||
form = DerivedBookForm({'title': title, 'author': self.writer.pk, 'isbn': '12345'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['__all__'], [u'Book with this Title and Author already exists.'])
|
||||
|
||||
def test_abstract_inherited_unique(self):
|
||||
title = 'Boss'
|
||||
isbn = '12345'
|
||||
dbook = DerivedBook.objects.create(title=title, author=self.writer, isbn=isbn)
|
||||
form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'isbn': isbn})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['isbn'], [u'Derived book with this Isbn already exists.'])
|
||||
|
||||
def test_abstract_inherited_unique_together(self):
|
||||
title = 'Boss'
|
||||
isbn = '12345'
|
||||
dbook = DerivedBook.objects.create(title=title, author=self.writer, isbn=isbn)
|
||||
form = DerivedBookForm({'title': 'Other', 'author': self.writer.pk, 'isbn': '9876', 'suffix1': u'0', 'suffix2': u'0'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['__all__'], [u'Derived book with this Suffix1 and Suffix2 already exists.'])
|
||||
|
||||
def test_explicitpk_unspecified(self):
|
||||
"""Test for primary_key being in the form and failing validation."""
|
||||
form = ExplicitPKForm({'key': u'', 'desc': u'' })
|
||||
self.assertFalse(form.is_valid())
|
||||
|
||||
def test_explicitpk_unique(self):
|
||||
"""Ensure keys and blank character strings are tested for uniqueness."""
|
||||
form = ExplicitPKForm({'key': u'key1', 'desc': u''})
|
||||
self.assertTrue(form.is_valid())
|
||||
form.save()
|
||||
form = ExplicitPKForm({'key': u'key1', 'desc': u''})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 3)
|
||||
self.assertEqual(form.errors['__all__'], [u'Explicit pk with this Key and Desc already exists.'])
|
||||
self.assertEqual(form.errors['desc'], [u'Explicit pk with this Desc already exists.'])
|
||||
self.assertEqual(form.errors['key'], [u'Explicit pk with this Key already exists.'])
|
||||
|
||||
def test_unique_for_date(self):
|
||||
p = Post.objects.create(title="Django 1.0 is released",
|
||||
slug="Django 1.0", subtitle="Finally", posted=datetime.date(2008, 9, 3))
|
||||
form = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-03'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['title'], [u'Title must be unique for Posted date.'])
|
||||
form = PostForm({'title': "Work on Django 1.1 begins", 'posted': '2008-09-03'})
|
||||
self.assertTrue(form.is_valid())
|
||||
form = PostForm({'title': "Django 1.0 is released", 'posted': '2008-09-04'})
|
||||
self.assertTrue(form.is_valid())
|
||||
form = PostForm({'slug': "Django 1.0", 'posted': '2008-01-01'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['slug'], [u'Slug must be unique for Posted year.'])
|
||||
form = PostForm({'subtitle': "Finally", 'posted': '2008-09-30'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(form.errors['subtitle'], [u'Subtitle must be unique for Posted month.'])
|
||||
form = PostForm({'subtitle': "Finally", "title": "Django 1.0 is released",
|
||||
"slug": "Django 1.0", 'posted': '2008-09-03'}, instance=p)
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
def test_inherited_unique_for_date(self):
|
||||
p = Post.objects.create(title="Django 1.0 is released",
|
||||
slug="Django 1.0", subtitle="Finally", posted=datetime.date(2008, 9, 3))
|
||||
form = DerivedPostForm({'title': "Django 1.0 is released", 'posted': '2008-09-03'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['title'], [u'Title must be unique for Posted date.'])
|
||||
form = DerivedPostForm({'title': "Work on Django 1.1 begins", 'posted': '2008-09-03'})
|
||||
self.assertTrue(form.is_valid())
|
||||
form = DerivedPostForm({'title': "Django 1.0 is released", 'posted': '2008-09-04'})
|
||||
self.assertTrue(form.is_valid())
|
||||
form = DerivedPostForm({'slug': "Django 1.0", 'posted': '2008-01-01'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(len(form.errors), 1)
|
||||
self.assertEqual(form.errors['slug'], [u'Slug must be unique for Posted year.'])
|
||||
form = DerivedPostForm({'subtitle': "Finally", 'posted': '2008-09-30'})
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertEqual(form.errors['subtitle'], [u'Subtitle must be unique for Posted month.'])
|
||||
form = DerivedPostForm({'subtitle': "Finally", "title": "Django 1.0 is released",
|
||||
"slug": "Django 1.0", 'posted': '2008-09-03'}, instance=p)
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
|
|
|
@ -9,26 +9,34 @@ class GetUniqueCheckTests(unittest.TestCase):
|
|||
def test_unique_fields_get_collected(self):
|
||||
m = UniqueFieldsModel()
|
||||
self.assertEqual(
|
||||
([('id',), ('unique_charfield',), ('unique_integerfield',)], []),
|
||||
([(UniqueFieldsModel, ('id',)),
|
||||
(UniqueFieldsModel, ('unique_charfield',)),
|
||||
(UniqueFieldsModel, ('unique_integerfield',))],
|
||||
[]),
|
||||
m._get_unique_checks()
|
||||
)
|
||||
|
||||
def test_unique_together_gets_picked_up_and_converted_to_tuple(self):
|
||||
m = UniqueTogetherModel()
|
||||
self.assertEqual(
|
||||
([('ifield', 'cfield',),('ifield', 'efield'), ('id',), ], []),
|
||||
([(UniqueTogetherModel, ('ifield', 'cfield',)),
|
||||
(UniqueTogetherModel, ('ifield', 'efield')),
|
||||
(UniqueTogetherModel, ('id',)), ],
|
||||
[]),
|
||||
m._get_unique_checks()
|
||||
)
|
||||
|
||||
def test_primary_key_is_considered_unique(self):
|
||||
m = CustomPKModel()
|
||||
self.assertEqual(([('my_pk_field',)], []), m._get_unique_checks())
|
||||
self.assertEqual(([(CustomPKModel, ('my_pk_field',))], []), m._get_unique_checks())
|
||||
|
||||
def test_unique_for_date_gets_picked_up(self):
|
||||
m = UniqueForDateModel()
|
||||
self.assertEqual((
|
||||
[('id',)],
|
||||
[('date', 'count', 'start_date'), ('year', 'count', 'end_date'), ('month', 'order', 'end_date')]
|
||||
[(UniqueForDateModel, ('id',))],
|
||||
[(UniqueForDateModel, 'date', 'count', 'start_date'),
|
||||
(UniqueForDateModel, 'year', 'count', 'end_date'),
|
||||
(UniqueForDateModel, 'month', 'order', 'end_date')]
|
||||
), m._get_unique_checks()
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue