diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py index ca650ac1af..91a14ad567 100644 --- a/django/db/backends/mysql/schema.py +++ b/django/db/backends/mysql/schema.py @@ -73,11 +73,9 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): """ first_field = model._meta.get_field(fields[0]) if first_field.get_internal_type() == 'ForeignKey': - constraint_names = self._constraint_names(model, fields[0], index=True) + constraint_names = self._constraint_names(model, [first_field.column], index=True) if not constraint_names: - self.execute( - self._create_index_sql(model, [model._meta.get_field(fields[0])], suffix="") - ) + self.execute(self._create_index_sql(model, [first_field], suffix="")) return super(DatabaseSchemaEditor, self)._delete_composed_index(model, fields, *args) def _set_field_new_type_null_status(self, field, new_type): diff --git a/docs/releases/1.8.3.txt b/docs/releases/1.8.3.txt index 39e08f904c..c6745f92c3 100644 --- a/docs/releases/1.8.3.txt +++ b/docs/releases/1.8.3.txt @@ -69,3 +69,5 @@ Bugfixes * Fixed ``prefetch_related()`` on databases other than PostgreSQL for models using UUID primary keys (:ticket:`24912`). + +* Fixed removing ``unique_together`` constraints on MySQL (:ticket:`24972`). diff --git a/tests/schema/models.py b/tests/schema/models.py index 4b37fcec37..2f0399232d 100644 --- a/tests/schema/models.py +++ b/tests/schema/models.py @@ -80,6 +80,15 @@ class BookWithSlug(models.Model): db_table = "schema_book" +class BookWithoutAuthor(models.Model): + title = models.CharField(max_length=100, db_index=True) + pub_date = models.DateTimeField() + + class Meta: + apps = new_apps + db_table = "schema_book" + + class IntegerPK(models.Model): i = models.IntegerField(primary_key=True) j = models.IntegerField(unique=True) diff --git a/tests/schema/tests.py b/tests/schema/tests.py index e388d318a3..aa35bfddc9 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -20,8 +20,9 @@ from django.test import TransactionTestCase, skipIfDBFeature from .fields import CustomManyToManyField, InheritedManyToManyField from .models import ( Author, AuthorWithDefaultHeight, AuthorWithEvenLongerName, Book, BookWeak, - BookWithLongName, BookWithO2O, BookWithSlug, IntegerPK, Note, NoteRename, - Tag, TagIndexed, TagM2MTest, TagUniqueRename, Thing, UniqueTest, new_apps, + BookWithLongName, BookWithO2O, BookWithoutAuthor, BookWithSlug, IntegerPK, + Note, NoteRename, Tag, TagIndexed, TagM2MTest, TagUniqueRename, Thing, + UniqueTest, new_apps, ) @@ -1185,6 +1186,28 @@ class SchemaTests(TransactionTestCase): with connection.schema_editor() as editor: editor.alter_unique_together(Book, [['author', 'title']], []) + def test_unique_together_with_fk_with_existing_index(self): + """ + Tests removing and adding unique_together constraints that include + a foreign key, where the foreign key is added after the model is + created. + """ + # Create the tables + with connection.schema_editor() as editor: + editor.create_model(Author) + editor.create_model(BookWithoutAuthor) + new_field = ForeignKey(Author) + new_field.set_attributes_from_name('author') + editor.add_field(BookWithoutAuthor, new_field) + # Ensure the fields aren't unique to begin with + self.assertEqual(Book._meta.unique_together, ()) + # Add the unique_together constraint + with connection.schema_editor() as editor: + editor.alter_unique_together(Book, [], [['author', 'title']]) + # Alter it back + with connection.schema_editor() as editor: + editor.alter_unique_together(Book, [['author', 'title']], []) + def test_index_together(self): """ Tests removing and adding index_together constraints on a model.