Loading django/db/migrations/writer.py +13 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import decimal import collections from importlib import import_module import os import sys import types from django.apps import apps Loading Loading @@ -158,7 +159,18 @@ class MigrationWriter(object): if '%s.%s' % (app_config.name, migrations_package_basename) == migrations_package_name: basedir = os.path.join(app_config.path, migrations_package_basename) else: raise ImportError("Cannot open migrations module %s for app %s" % (migrations_package_name, self.migration.app_label)) # In case of using MIGRATION_MODULES setting and the custom # package doesn't exist, create one. package_dirs = migrations_package_name.split(".") create_path = os.path.join(sys.path[0], *package_dirs) if not os.path.isdir(create_path): os.makedirs(create_path) for i in range(1, len(package_dirs) + 1): init_dir = os.path.join(sys.path[0], *package_dirs[:i]) init_path = os.path.join(init_dir, "__init__.py") if not os.path.isfile(init_path): open(init_path, "w").close() return os.path.join(create_path, self.filename) return os.path.join(basedir, self.filename) @classmethod Loading docs/ref/settings.txt +3 −0 Original line number Diff line number Diff line Loading @@ -1757,6 +1757,9 @@ Example:: In this case, migrations pertaining to the ``blog`` app will be contained in the ``blog.db_migrations`` package. :djadmin:`makemigrations` will automatically create the package if it doesn't already exist. .. setting:: MONTH_DAY_FORMAT MONTH_DAY_FORMAT Loading tests/migrations/test_commands.py +35 −0 Original line number Diff line number Diff line Loading @@ -413,3 +413,38 @@ class MakeMigrationsTests(MigrationTestBase): self.assertIn("migrations.AddField(", stdout.getvalue()) self.assertIn("model_name='sillymodel',", stdout.getvalue()) self.assertIn("name='silly_char',", stdout.getvalue()) @override_system_checks([]) @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_path_doesnt_exist.foo.bar"}) def test_makemigrations_migrations_modules_path_not_exist(self): """ Ticket #22682 -- Makemigrations fails when specifying custom location for migration files (using MIGRATION_MODULES) if the custom path doesn't already exist. """ class SillyModel(models.Model): silly_field = models.BooleanField(default=False) class Meta: app_label = "migrations" stdout = six.StringIO() call_command("makemigrations", "migrations", stdout=stdout) # Command output indicates the migration is created. self.assertIn(" - Create model SillyModel", stdout.getvalue()) # Migrations file is actually created in the expected path. self.assertTrue(os.path.isfile(os.path.join(self.test_dir, "test_migrations_path_doesnt_exist", "foo", "bar", "0001_initial.py"))) os.chdir(self.test_dir) try: self._rmrf(os.path.join(self.test_dir, "test_migrations_path_doesnt_exist")) pass except OSError: pass os.chdir(self._cwd) Loading
django/db/migrations/writer.py +13 −1 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import decimal import collections from importlib import import_module import os import sys import types from django.apps import apps Loading Loading @@ -158,7 +159,18 @@ class MigrationWriter(object): if '%s.%s' % (app_config.name, migrations_package_basename) == migrations_package_name: basedir = os.path.join(app_config.path, migrations_package_basename) else: raise ImportError("Cannot open migrations module %s for app %s" % (migrations_package_name, self.migration.app_label)) # In case of using MIGRATION_MODULES setting and the custom # package doesn't exist, create one. package_dirs = migrations_package_name.split(".") create_path = os.path.join(sys.path[0], *package_dirs) if not os.path.isdir(create_path): os.makedirs(create_path) for i in range(1, len(package_dirs) + 1): init_dir = os.path.join(sys.path[0], *package_dirs[:i]) init_path = os.path.join(init_dir, "__init__.py") if not os.path.isfile(init_path): open(init_path, "w").close() return os.path.join(create_path, self.filename) return os.path.join(basedir, self.filename) @classmethod Loading
docs/ref/settings.txt +3 −0 Original line number Diff line number Diff line Loading @@ -1757,6 +1757,9 @@ Example:: In this case, migrations pertaining to the ``blog`` app will be contained in the ``blog.db_migrations`` package. :djadmin:`makemigrations` will automatically create the package if it doesn't already exist. .. setting:: MONTH_DAY_FORMAT MONTH_DAY_FORMAT Loading
tests/migrations/test_commands.py +35 −0 Original line number Diff line number Diff line Loading @@ -413,3 +413,38 @@ class MakeMigrationsTests(MigrationTestBase): self.assertIn("migrations.AddField(", stdout.getvalue()) self.assertIn("model_name='sillymodel',", stdout.getvalue()) self.assertIn("name='silly_char',", stdout.getvalue()) @override_system_checks([]) @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations_path_doesnt_exist.foo.bar"}) def test_makemigrations_migrations_modules_path_not_exist(self): """ Ticket #22682 -- Makemigrations fails when specifying custom location for migration files (using MIGRATION_MODULES) if the custom path doesn't already exist. """ class SillyModel(models.Model): silly_field = models.BooleanField(default=False) class Meta: app_label = "migrations" stdout = six.StringIO() call_command("makemigrations", "migrations", stdout=stdout) # Command output indicates the migration is created. self.assertIn(" - Create model SillyModel", stdout.getvalue()) # Migrations file is actually created in the expected path. self.assertTrue(os.path.isfile(os.path.join(self.test_dir, "test_migrations_path_doesnt_exist", "foo", "bar", "0001_initial.py"))) os.chdir(self.test_dir) try: self._rmrf(os.path.join(self.test_dir, "test_migrations_path_doesnt_exist")) pass except OSError: pass os.chdir(self._cwd)