From 19e437497172640a1b488228fb218719f9f7f5b4 Mon Sep 17 00:00:00 2001 From: Baptiste Mispelon Date: Fri, 6 Dec 2013 15:05:12 +0100 Subject: [PATCH] Fixed ModelState breaking when unique_together has unhashable elements. --- django/db/migrations/state.py | 5 +++-- django/db/models/options.py | 9 ++++++--- tests/migrations/test_state.py | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py index 87cc0cb80e..769b0005f8 100644 --- a/django/db/migrations/state.py +++ b/django/db/migrations/state.py @@ -1,6 +1,6 @@ from django.db import models from django.db.models.loading import BaseAppCache -from django.db.models.options import DEFAULT_NAMES +from django.db.models.options import DEFAULT_NAMES, normalize_unique_together from django.utils import six from django.utils.module_loading import import_by_path @@ -127,7 +127,8 @@ class ModelState(object): continue elif name in model._meta.original_attrs: if name == "unique_together": - options[name] = set(model._meta.original_attrs["unique_together"]) + ut = model._meta.original_attrs["unique_together"] + options[name] = set(normalize_unique_together(ut)) else: options[name] = model._meta.original_attrs[name] # Make our record diff --git a/django/db/models/options.py b/django/db/models/options.py index 5c4a9dcad7..b14e61573c 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -32,10 +32,13 @@ 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)): + if not unique_together: + return () + first_element = next(iter(unique_together)) + if not isinstance(first_element, (tuple, list)): unique_together = (unique_together,) - return unique_together + # Normalize everything to tuples + return tuple(tuple(ut) for ut in unique_together) @python_2_unicode_compatible diff --git a/tests/migrations/test_state.py b/tests/migrations/test_state.py index 889367b41d..9cbbbf294d 100644 --- a/tests/migrations/test_state.py +++ b/tests/migrations/test_state.py @@ -55,7 +55,7 @@ class StateTests(TestCase): self.assertEqual(author_state.fields[1][1].max_length, 255) self.assertEqual(author_state.fields[2][1].null, False) self.assertEqual(author_state.fields[3][1].null, True) - self.assertEqual(author_state.options, {"unique_together": set(("name", "bio"))}) + self.assertEqual(author_state.options, {"unique_together": {("name", "bio")}}) self.assertEqual(author_state.bases, (models.Model, )) self.assertEqual(book_state.app_label, "migrations")