diff --git a/django/forms/models.py b/django/forms/models.py
index 2a3f8bd..09b46b5 100644
a
|
b
|
class BaseModelForm(BaseForm):
|
342 | 342 | Calls the instance's validate_unique() method and updates the form's |
343 | 343 | validation errors if any were raised. |
344 | 344 | """ |
345 | | exclude = self._get_validation_exclusions() |
346 | 345 | try: |
347 | | self.instance.validate_unique(exclude=exclude) |
| 346 | self.instance.validate_unique() |
348 | 347 | except ValidationError, e: |
349 | 348 | self._update_errors(e.message_dict) |
350 | 349 | |
diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py
index 60319ea..36579e2 100644
a
|
b
|
class Reservation(models.Model):
|
670 | 670 | start_date = models.DateTimeField() |
671 | 671 | price = models.IntegerField() |
672 | 672 | |
| 673 | class UniqueTogether(models.Model): |
| 674 | t1 = models.CharField(max_length=255, blank=True, null=True) |
| 675 | t2 = models.CharField(max_length=255, blank=True, null=True) |
| 676 | t3 = models.CharField(max_length=255, blank=True, null=True) |
| 677 | |
| 678 | class Meta: |
| 679 | unique_together = ['t1','t2','t3'] |
| 680 | |
| 681 | class UniqueTogetherAdmin(admin.ModelAdmin): |
| 682 | list_display = ['t3', 't1', 't2'] |
| 683 | list_editable = ['t1', 't2',] |
| 684 | |
673 | 685 | admin.site.register(Article, ArticleAdmin) |
674 | 686 | admin.site.register(CustomArticle, CustomArticleAdmin) |
675 | 687 | admin.site.register(Section, save_as=True, inlines=[ArticleInline]) |
… |
… |
admin.site.register(CyclicOne)
|
706 | 718 | admin.site.register(CyclicTwo) |
707 | 719 | admin.site.register(WorkHour, WorkHourAdmin) |
708 | 720 | admin.site.register(Reservation) |
| 721 | admin.site.register(UniqueTogether, UniqueTogetherAdmin) |
709 | 722 | |
710 | 723 | # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. |
711 | 724 | # That way we cover all four cases: |
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
index acbbbfc..250af13 100644
a
|
b
|
from models import (Article, BarAccount, CustomArticle, EmptyModel,
|
35 | 35 | Person, Persona, Picture, Podcast, Section, Subscriber, Vodcast, |
36 | 36 | Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit, |
37 | 37 | Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee, |
38 | | Question, Answer, Inquisition, Actor) |
| 38 | Question, Answer, Inquisition, Actor, UniqueTogether) |
39 | 39 | |
40 | 40 | |
41 | 41 | class AdminViewBasicTest(TestCase): |
… |
… |
class AdminViewListEditable(TestCase):
|
1338 | 1338 | # 1 select per object = 3 selects |
1339 | 1339 | self.assertEqual(response.content.count("<select"), 4) |
1340 | 1340 | |
| 1341 | def test_partial_unique_together(self): |
| 1342 | """ Ensure that no IntegrityError is raised when editing some (but |
| 1343 | not all) of the values specified as unique_together. Refs #13091. |
| 1344 | """ |
| 1345 | UniqueTogether.objects.create(t1='a', t2='b', t3='c') |
| 1346 | UniqueTogether.objects.create(t1='b', t2='b', t3='a') |
| 1347 | UniqueTogether.objects.create(t1='c', t2='a', t3='c') |
| 1348 | data = { |
| 1349 | "form-TOTAL_FORMS": "3", |
| 1350 | "form-INITIAL_FORMS": "3", |
| 1351 | "form-MAX_NUM_FORMS": "0", |
| 1352 | |
| 1353 | "form-0-t1": "a", |
| 1354 | "form-0-t2": "b", |
| 1355 | "form-0-t3": "c", |
| 1356 | "form-0-id": "1", |
| 1357 | |
| 1358 | "form-1-t1": "a", |
| 1359 | "form-1-t2": "b", |
| 1360 | "form-1-t3": "c", |
| 1361 | "form-1-id": "2", |
| 1362 | |
| 1363 | "form-2-t1": "a", |
| 1364 | "form-2-t2": "b", |
| 1365 | "form-2-t3": "c", |
| 1366 | "form-2-id": "3", |
| 1367 | |
| 1368 | "_save": "Save", |
| 1369 | } |
| 1370 | response = self.client.post('/test_admin/admin/admin_views/uniquetogether/', data) |
| 1371 | self.assertContains(response, 'Please correct the errors below.') |
| 1372 | |
1341 | 1373 | def test_post_messages(self): |
1342 | 1374 | # Ticket 12707: Saving inline editable should not show admin |
1343 | 1375 | # action warnings |