Commit 4dbd95ad authored by Javed Khan's avatar Javed Khan Committed by Tim Graham
Browse files

Fixed #21236 -- Allowed migrations to work with unique_together tuples.

Thanks hjwp for the report.
parent 67f5dffb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
from .base import Operation
from django.db import models, router
from django.db.models.options import normalize_unique_together
from django.db.migrations.state import ModelState


@@ -108,6 +109,7 @@ class AlterUniqueTogether(Operation):

    def __init__(self, name, unique_together):
        self.name = name
        unique_together = normalize_unique_together(unique_together)
        self.unique_together = set(tuple(cons) for cons in unique_together)

    def state_forwards(self, app_label, state):
+11 −6
Original line number Diff line number Diff line
@@ -25,6 +25,16 @@ DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering',
                 'index_together', 'app_cache', 'default_permissions',
                 'select_on_save')

def normalize_unique_together(unique_together):
    """
    unique_together can be either a tuple of tuples, or a single
    tuple of two strings. Normalize it to a tuple of tuples, so that
    calling code can uniformly expect that.
    """
    if unique_together and not isinstance(unique_together[0], (tuple, list)):
        unique_together = (unique_together,)
    return unique_together

@python_2_unicode_compatible
class Options(object):
    def __init__(self, meta, app_label=None):
@@ -108,13 +118,8 @@ class Options(object):
                    setattr(self, attr_name, getattr(self.meta, attr_name))
                    self.original_attrs[attr_name] = getattr(self, attr_name)

            # unique_together can be either a tuple of tuples, or a single
            # tuple of two strings. Normalize it to a tuple of tuples, so that
            # calling code can uniformly expect that.
            ut = meta_attrs.pop('unique_together', self.unique_together)
            if ut and not isinstance(ut[0], (tuple, list)):
                ut = (ut,)
            self.unique_together = ut
            self.unique_together = normalize_unique_together(ut)

            # verbose_name_plural is a special case because it uses a 's'
            # by default.
+4 −0
Original line number Diff line number Diff line
@@ -267,6 +267,10 @@ class OperationTests(MigrationTestBase):
        cursor.execute("INSERT INTO test_alunto_pony (id, pink, weight) VALUES (1, 1, 1)")
        cursor.execute("INSERT INTO test_alunto_pony (id, pink, weight) VALUES (2, 1, 1)")
        cursor.execute("DELETE FROM test_alunto_pony")
        # Test flat unique_together
        operation = migrations.AlterUniqueTogether("Pony", ("pink", "weight"))
        operation.state_forwards("test_alunto", new_state)
        self.assertEqual(len(new_state.models["test_alunto", "pony"].options.get("unique_together", set())), 1)

    def test_alter_index_together(self):
        """