diff --git a/django/db/models/options.py b/django/db/models/options.py index b5d8b1bb9ac..6838456ddd6 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -231,12 +231,25 @@ class Options(object): """ Has this model been swapped out for another? If so, return the model name of the replacement; otherwise, return None. + + For historical reasons, model name lookups using get_model() are + case insensitive, so we make sure we are case insensitive here. """ if self.swappable: - model_label = '%s.%s' % (self.app_label, self.object_name) + model_label = '%s.%s' % (self.app_label, self.object_name.lower()) swapped_for = getattr(settings, self.swappable, None) - if swapped_for not in (None, model_label): - return swapped_for + if swapped_for: + try: + swapped_label, swapped_object = swapped_for.split('.') + except ValueError: + # setting not in the format app_label.model_name + # raising ImproperlyConfigured here causes problems with + # test cleanup code - instead it is raised in get_user_model + # or as part of validation. + return swapped_for + + if '%s.%s' % (swapped_label, swapped_object.lower()) not in (None, model_label): + return swapped_for return None swapped = property(_swapped) diff --git a/tests/regressiontests/swappable_models/tests.py b/tests/regressiontests/swappable_models/tests.py index 75644e32aa8..089b391416f 100644 --- a/tests/regressiontests/swappable_models/tests.py +++ b/tests/regressiontests/swappable_models/tests.py @@ -9,6 +9,8 @@ from django.db.models.loading import cache from django.test import TestCase from django.test.utils import override_settings +from regressiontests.swappable_models.models import Article + class SwappableModelTests(TestCase): def setUp(self): @@ -44,3 +46,13 @@ class SwappableModelTests(TestCase): for ct in ContentType.objects.all()] self.assertIn(('swappable_models', 'alternatearticle'), apps_models) self.assertNotIn(('swappable_models', 'article'), apps_models) + + @override_settings(TEST_ARTICLE_MODEL='swappable_models.article') + def test_case_insensitive(self): + "Model names are case insensitive. Check that model swapping honors this." + try: + Article.objects.all() + except AttributeError: + self.fail('Swappable model names should be case insensitive.') + + self.assertIsNone(Article._meta.swapped)