From 58d357fc65ab0d3b16184db81059b9cef3b83c10 Mon Sep 17 00:00:00 2001 From: Hameed Gifford Date: Tue, 8 Mar 2022 00:22:03 -0500 Subject: [PATCH] Fixed #33563 -- Fixed contenttype reverse data migration crash with a multiple databases setup. --- .../0002_remove_content_type_name.py | 3 +- tests/contenttypes_tests/test_migrations.py | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/contenttypes_tests/test_migrations.py diff --git a/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py b/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py index 3bee3a864f..cb026e7503 100644 --- a/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py +++ b/django/contrib/contenttypes/migrations/0002_remove_content_type_name.py @@ -2,8 +2,9 @@ from django.db import migrations, models def add_legacy_name(apps, schema_editor): + alias = schema_editor.connection.alias ContentType = apps.get_model("contenttypes", "ContentType") - for ct in ContentType.objects.all(): + for ct in ContentType.objects.using(alias): try: ct.name = apps.get_model(ct.app_label, ct.model)._meta.object_name except LookupError: diff --git a/tests/contenttypes_tests/test_migrations.py b/tests/contenttypes_tests/test_migrations.py new file mode 100644 index 0000000000..7482473c98 --- /dev/null +++ b/tests/contenttypes_tests/test_migrations.py @@ -0,0 +1,31 @@ +from importlib import import_module + +from django.apps import apps +from django.contrib.auth.models import Permission +from django.contrib.contenttypes.models import ContentType +from django.db import DEFAULT_DB_ALIAS, connections +from django.test import TransactionTestCase + +remove_content_type_name = import_module( + "django.contrib.contenttypes.migrations.0002_remove_content_type_name" +) + + +class MultiDBRemoveContentTypeNameTests(TransactionTestCase): + databases = {"default", "other"} + available_apps = ["django.contrib.auth", "django.contrib.contenttypes"] + + def test_add_legacy_name_other_database(self): + # add_legacy_name() should update ContentType objects in the specified + # database. Remove ContentTypes from the default database to distinct + # from which database they are fetched. + Permission.objects.all().delete() + ContentType.objects.all().delete() + # ContentType.name in the current version is a property and cannot be + # set, so an AttributeError is raised with the other database. + with self.assertRaises(AttributeError): + with connections["other"].schema_editor() as editor: + remove_content_type_name.add_legacy_name(apps, editor) + # ContentType were removed from the default database. + with connections[DEFAULT_DB_ALIAS].schema_editor() as editor: + remove_content_type_name.add_legacy_name(apps, editor)