Browse files

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

Thanks to Tim for the review.
  • Loading branch information...
1 parent 4cfe6ba commit 331d79a77d48e1a46df0290689d4d865e67221c4 @bmispelon bmispelon committed Nov 20, 2013
Showing with 36 additions and 1 deletion.
  1. +1 −0 django/db/models/options.py
  2. +35 −1 tests/validation/test_unique.py
View
1 django/db/models/options.py
@@ -32,6 +32,7 @@ def normalize_unique_together(unique_together):
tuple of two strings. Normalize it to a tuple of tuples, so that
calling code can uniformly expect that.
"""
+ unique_together = tuple(unique_together)
if unique_together and not isinstance(unique_together[0], (tuple, list)):
unique_together = (unique_together,)
return unique_together
View
36 tests/validation/test_unique.py
@@ -4,6 +4,8 @@
import unittest
from django.core.exceptions import ValidationError
+from django.db import models
+from django.db.models.loading import BaseAppCache
from django.test import TestCase
from .models import (CustomPKModel, UniqueTogetherModel, UniqueFieldsModel,
@@ -25,13 +27,45 @@ def test_unique_fields_get_collected(self):
def test_unique_together_gets_picked_up_and_converted_to_tuple(self):
m = UniqueTogetherModel()
self.assertEqual(
- ([(UniqueTogetherModel, ('ifield', 'cfield',)),
+ ([(UniqueTogetherModel, ('ifield', 'cfield')),
(UniqueTogetherModel, ('ifield', 'efield')),
(UniqueTogetherModel, ('id',)), ],
[]),
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):
m = CustomPKModel()
self.assertEqual(([(CustomPKModel, ('my_pk_field',))], []), m._get_unique_checks())

0 comments on commit 331d79a

Please sign in to comment.