Loading django/db/models/options.py +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading tests/validation/test_unique.py +35 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ import datetime 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, Loading @@ -25,13 +27,45 @@ class GetUniqueCheckTests(unittest.TestCase): 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()) Loading Loading
django/db/models/options.py +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
tests/validation/test_unique.py +35 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ import datetime 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, Loading @@ -25,13 +27,45 @@ class GetUniqueCheckTests(unittest.TestCase): 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()) Loading