Skip to content

Commit

Permalink
Fixed #21283 -- Added support for migrations if models is a package.
Browse files Browse the repository at this point in the history
Thanks Markus Holtermann for the report.
  • Loading branch information
loic authored and timgraham committed Oct 19, 2013
1 parent 96d1d4e commit 5841104
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 13 deletions.
4 changes: 2 additions & 2 deletions django/db/migrations/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
18 changes: 10 additions & 8 deletions django/db/migrations/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions django/db/models/loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
30 changes: 27 additions & 3 deletions tests/migrations/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 _


Expand Down Expand Up @@ -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

0 comments on commit 5841104

Please sign in to comment.