Fixed #21469 -- Allow set objects in Meta.unique_together.

Thanks to Tim for the review.
This commit is contained in:
Baptiste Mispelon 2013-11-20 10:28:22 +01:00
parent 4cfe6ba6a3
commit 331d79a77d
2 changed files with 36 additions and 1 deletions

View File

@ -32,6 +32,7 @@ def normalize_unique_together(unique_together):
tuple of two strings. Normalize it to a tuple of tuples, so that tuple of two strings. Normalize it to a tuple of tuples, so that
calling code can uniformly expect that. calling code can uniformly expect that.
""" """
unique_together = tuple(unique_together)
if unique_together and not isinstance(unique_together[0], (tuple, list)): if unique_together and not isinstance(unique_together[0], (tuple, list)):
unique_together = (unique_together,) unique_together = (unique_together,)
return unique_together return unique_together

View File

@ -4,6 +4,8 @@ import datetime
import unittest import unittest
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models
from django.db.models.loading import BaseAppCache
from django.test import TestCase from django.test import TestCase
from .models import (CustomPKModel, UniqueTogetherModel, UniqueFieldsModel, from .models import (CustomPKModel, UniqueTogetherModel, UniqueFieldsModel,
@ -25,13 +27,45 @@ class GetUniqueCheckTests(unittest.TestCase):
def test_unique_together_gets_picked_up_and_converted_to_tuple(self): def test_unique_together_gets_picked_up_and_converted_to_tuple(self):
m = UniqueTogetherModel() m = UniqueTogetherModel()
self.assertEqual( self.assertEqual(
([(UniqueTogetherModel, ('ifield', 'cfield',)), ([(UniqueTogetherModel, ('ifield', 'cfield')),
(UniqueTogetherModel, ('ifield', 'efield')), (UniqueTogetherModel, ('ifield', 'efield')),
(UniqueTogetherModel, ('id',)), ], (UniqueTogetherModel, ('id',)), ],
[]), []),
m._get_unique_checks() m._get_unique_checks()
) )
def test_unique_together_normalization(self):
"""
Test the Meta.unique_together normalization with different sorts of
objects.
"""
data = {
'2-tuple': (('foo', 'bar'),
(('foo', 'bar'),)),
'list': (['foo', 'bar'],
(('foo', 'bar'),)),
'already normalized': ((('foo', 'bar'), ('bar', 'baz')),
(('foo', 'bar'), ('bar', 'baz'))),
'set': ({('foo', 'bar'), ('bar', 'baz')}, # Ref #21469
(('foo', 'bar'), ('bar', 'baz'))),
}
for test_name, (unique_together, normalized) in data.items():
class M(models.Model):
foo = models.IntegerField()
bar = models.IntegerField()
baz = models.IntegerField()
Meta = type(str('Meta'), (), {
'unique_together': unique_together,
'app_cache': BaseAppCache()
})
checks, _ = M()._get_unique_checks()
for t in normalized:
check = (M, t)
self.assertIn(check, checks)
def test_primary_key_is_considered_unique(self): def test_primary_key_is_considered_unique(self):
m = CustomPKModel() m = CustomPKModel()
self.assertEqual(([(CustomPKModel, ('my_pk_field',))], []), m._get_unique_checks()) self.assertEqual(([(CustomPKModel, ('my_pk_field',))], []), m._get_unique_checks())