Fixed #21283 -- Added support for migrations if models is a package.
Thanks Markus Holtermann for the report.
This commit is contained in:
parent
96d1d4e292
commit
584110417f
|
@ -41,8 +41,8 @@ class MigrationLoader(object):
|
||||||
def migrations_module(cls, app_label):
|
def migrations_module(cls, app_label):
|
||||||
if app_label in settings.MIGRATION_MODULES:
|
if app_label in settings.MIGRATION_MODULES:
|
||||||
return settings.MIGRATION_MODULES[app_label]
|
return settings.MIGRATION_MODULES[app_label]
|
||||||
app = cache.get_app(app_label)
|
else:
|
||||||
return ".".join(app.__name__.split(".")[:-1] + ["migrations"])
|
return '%s.migrations' % cache.get_app_package(app_label)
|
||||||
|
|
||||||
def load_disk(self):
|
def load_disk(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -61,20 +61,22 @@ class MigrationWriter(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self):
|
def path(self):
|
||||||
migrations_module_name = MigrationLoader.migrations_module(self.migration.app_label)
|
migrations_package_name = MigrationLoader.migrations_module(self.migration.app_label)
|
||||||
app_module = cache.get_app(self.migration.app_label)
|
|
||||||
# See if we can import the migrations module directly
|
# See if we can import the migrations module directly
|
||||||
try:
|
try:
|
||||||
migrations_module = import_module(migrations_module_name)
|
migrations_module = import_module(migrations_package_name)
|
||||||
basedir = os.path.dirname(migrations_module.__file__)
|
basedir = os.path.dirname(migrations_module.__file__)
|
||||||
except ImportError:
|
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
|
# Alright, see if it's a direct submodule of the app
|
||||||
oneup = ".".join(migrations_module_name.split(".")[:-1])
|
if '%s.%s' % (app_package_name, migrations_package_basename) == migrations_package_name:
|
||||||
app_oneup = ".".join(app_module.__name__.split(".")[:-1])
|
basedir = os.path.join(app_path, migrations_package_basename)
|
||||||
if oneup == app_oneup:
|
|
||||||
basedir = os.path.join(os.path.dirname(app_module.__file__), migrations_module_name.split(".")[-1])
|
|
||||||
else:
|
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)
|
return os.path.join(basedir, self.filename)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -185,6 +185,12 @@ class BaseAppCache(object):
|
||||||
|
|
||||||
return [elt[0] for elt in apps]
|
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):
|
def _get_app_path(self, app):
|
||||||
if hasattr(app, '__path__'): # models/__init__.py package
|
if hasattr(app, '__path__'): # models/__init__.py package
|
||||||
app_path = app.__path__[0]
|
app_path = app.__path__[0]
|
||||||
|
@ -380,6 +386,7 @@ cache = AppCache()
|
||||||
# These methods were always module level, so are kept that way for backwards
|
# These methods were always module level, so are kept that way for backwards
|
||||||
# compatibility.
|
# compatibility.
|
||||||
get_apps = cache.get_apps
|
get_apps = cache.get_apps
|
||||||
|
get_app_package = cache.get_app_package
|
||||||
get_app_path = cache.get_app_path
|
get_app_path = cache.get_app_path
|
||||||
get_app_paths = cache.get_app_paths
|
get_app_paths = cache.get_app_paths
|
||||||
get_app = cache.get_app
|
get_app = cache.get_app
|
||||||
|
|
|
@ -2,12 +2,15 @@
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import copy
|
||||||
import datetime
|
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 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 _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,3 +98,24 @@ class WriterTests(TestCase):
|
||||||
# Just make sure it runs for now, and that things look alright.
|
# Just make sure it runs for now, and that things look alright.
|
||||||
result = self.safe_exec(output)
|
result = self.safe_exec(output)
|
||||||
self.assertIn("Migration", result)
|
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
|
||||||
|
|
Loading…
Reference in New Issue