diff --git a/django/core/management/templates.py b/django/core/management/templates.py index c9cdc255661f..633eed781dec 100644 --- a/django/core/management/templates.py +++ b/django/core/management/templates.py @@ -5,7 +5,7 @@ import shutil import stat import tempfile -from importlib import import_module +from importlib.util import find_spec from urllib.request import build_opener import django @@ -275,12 +275,8 @@ def validate_name(self, name, name_or_dir="name"): type=name_or_dir, ) ) - # Check it cannot be imported. - try: - import_module(name) - except ImportError: - pass - else: + # Check that __spec__ doesn't exist. + if find_spec(name) is not None: raise CommandError( "'{name}' conflicts with the name of an existing Python " "module and cannot be used as {an} {app} {type}. Please try " diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index 57fbc454ff93..7f39d7fcfc88 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -2447,6 +2447,28 @@ def test_importable_project_name(self): ) self.assertFalse(os.path.exists(testproject_dir)) + def test_command_does_not_import(self): + """ + startproject doesn't import modules (and cannot be fooled by a module + raising ImportError). + """ + bad_name = "raises_import_error" + args = ["startproject", bad_name] + testproject_dir = os.path.join(self.test_dir, bad_name) + + with open(os.path.join(self.test_dir, "raises_import_error.py"), "w") as f: + f.write("raise ImportError") + + out, err = self.run_django_admin(args) + self.assertOutput( + err, + "CommandError: 'raises_import_error' conflicts with the name of an " + "existing Python module and cannot be used as a project name. Please try " + "another name.", + ) + self.assertNoOutput(out) + self.assertFalse(os.path.exists(testproject_dir)) + def test_simple_project_different_directory(self): """ The startproject management command creates a project in a specific