Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #21283 -- Added support for migrations if models is a package.

Thanks Markus Holtermann for the report.
  • Loading branch information...
commit 584110417f6a3c16cc0c6723825a21940a9a2bc4 1 parent 96d1d4e
@loic loic authored timgraham committed
View
4 django/db/migrations/loader.py
@@ -41,8 +41,8 @@ def __init__(self, connection):
def migrations_module(cls, app_label):
if app_label in settings.MIGRATION_MODULES:
return settings.MIGRATION_MODULES[app_label]
- app = cache.get_app(app_label)
- return ".".join(app.__name__.split(".")[:-1] + ["migrations"])
+ else:
+ return '%s.migrations' % cache.get_app_package(app_label)
def load_disk(self):
"""
View
18 django/db/migrations/writer.py
@@ -61,20 +61,22 @@ def filename(self):
@property
def path(self):
- migrations_module_name = MigrationLoader.migrations_module(self.migration.app_label)
- app_module = cache.get_app(self.migration.app_label)
+ migrations_package_name = MigrationLoader.migrations_module(self.migration.app_label)
# See if we can import the migrations module directly
try:
- migrations_module = import_module(migrations_module_name)
+ migrations_module = import_module(migrations_package_name)
basedir = os.path.dirname(migrations_module.__file__)
except ImportError:
+ app = cache.get_app(self.migration.app_label)
+ app_path = cache._get_app_path(app)
+ app_package_name = cache._get_app_package(app)
+ migrations_package_basename = migrations_package_name.split(".")[-1]
+
# Alright, see if it's a direct submodule of the app
- oneup = ".".join(migrations_module_name.split(".")[:-1])
- app_oneup = ".".join(app_module.__name__.split(".")[:-1])
- if oneup == app_oneup:
- basedir = os.path.join(os.path.dirname(app_module.__file__), migrations_module_name.split(".")[-1])
+ if '%s.%s' % (app_package_name, migrations_package_basename) == migrations_package_name:
+ basedir = os.path.join(app_path, migrations_package_basename)
else:
- raise ImportError("Cannot open migrations module %s for app %s" % (migrations_module_name, self.migration.app_label))
+ raise ImportError("Cannot open migrations module %s for app %s" % (migrations_package_name, self.migration.app_label))
return os.path.join(basedir, self.filename)
@classmethod
View
7 django/db/models/loading.py
@@ -185,6 +185,12 @@ def get_apps(self):
return [elt[0] for elt in apps]
+ def _get_app_package(self, app):
+ return '.'.join(app.__name__.split('.')[:-1])
+
+ def get_app_package(self, app_label):
+ return self._get_app_package(self.get_app(app_label))
+
def _get_app_path(self, app):
if hasattr(app, '__path__'): # models/__init__.py package
app_path = app.__path__[0]
@@ -380,6 +386,7 @@ def __init__(self):
# These methods were always module level, so are kept that way for backwards
# compatibility.
get_apps = cache.get_apps
+get_app_package = cache.get_app_package
get_app_path = cache.get_app_path
get_app_paths = cache.get_app_paths
get_app = cache.get_app
View
0  tests/migrations/migrations_test_apps/__init__.py
No changes.
View
0  tests/migrations/migrations_test_apps/normal/__init__.py
No changes.
View
0  tests/migrations/migrations_test_apps/normal/models.py
No changes.
View
0  tests/migrations/migrations_test_apps/with_package_model/__init__.py
No changes.
View
0  tests/migrations/migrations_test_apps/with_package_model/models/__init__.py
No changes.
View
30 tests/migrations/test_writer.py
@@ -2,12 +2,15 @@
from __future__ import unicode_literals
+import copy
import datetime
+import os
-from django.utils import six
-from django.test import TestCase
-from django.db.migrations.writer import MigrationWriter
from django.db import models, migrations
+from django.db.migrations.writer import MigrationWriter
+from django.db.models.loading import cache
+from django.test import TestCase, override_settings
+from django.utils import six
from django.utils.translation import ugettext_lazy as _
@@ -95,3 +98,24 @@ def test_simple_migration(self):
# Just make sure it runs for now, and that things look alright.
result = self.safe_exec(output)
self.assertIn("Migration", result)
+
+ def test_migration_path(self):
+ _old_app_store = copy.deepcopy(cache.app_store)
+
+ test_apps = [
+ 'migrations.migrations_test_apps.normal',
+ 'migrations.migrations_test_apps.with_package_model',
+ ]
+
+ base_dir = os.path.dirname(os.path.dirname(__file__))
+
+ try:
+ with override_settings(INSTALLED_APPS=test_apps):
+ for app in test_apps:
+ cache.load_app(app)
+ migration = migrations.Migration('0001_initial', app.split('.')[-1])
+ expected_path = os.path.join(base_dir, *(app.split('.') + ['migrations', '0001_initial.py']))
+ writer = MigrationWriter(migration)
+ self.assertEqual(writer.path, expected_path)
+ finally:
+ cache.app_store = _old_app_store
Please sign in to comment.
Something went wrong with that request. Please try again.