Makemigration command now works

This commit is contained in:
Andrew Godwin 2013-06-19 16:23:52 +01:00
parent ab5cbae9b7
commit f25a385a5e
7 changed files with 87 additions and 7 deletions

View File

@ -1,4 +1,5 @@
import sys
import os
from optparse import make_option
from django.core.management.base import BaseCommand
@ -8,6 +9,7 @@ from django.db import connections
from django.db.migrations.loader import MigrationLoader
from django.db.migrations.autodetector import MigrationAutodetector, InteractiveMigrationQuestioner
from django.db.migrations.state import ProjectState
from django.db.migrations.writer import MigrationWriter
from django.db.models.loading import cache
@ -49,4 +51,30 @@ class Command(BaseCommand):
if app_labels:
changes = autodetector.trim_to_apps(changes, app_labels)
print changes
# No changes? Tell them.
if not changes:
if len(app_labels) == 1:
self.stdout.write("No changes detected in app '%s'" % app_labels.pop())
elif len(app_labels) > 1:
self.stdout.write("No changes detected in apps '%s'" % ("', '".join(app_labels)))
else:
self.stdout.write("No changes detected")
return
for app_label, migrations in changes.items():
self.stdout.write(self.style.MIGRATE_HEADING("Migrations for '%s':" % app_label) + "\n")
for migration in migrations:
# Describe the migration
writer = MigrationWriter(migration)
self.stdout.write(" %s:\n" % (self.style.MIGRATE_LABEL(writer.filename),))
for operation in migration.operations:
self.stdout.write(" - %s\n" % operation.describe())
# Write it
migrations_directory = os.path.dirname(writer.path)
if not os.path.isdir(migrations_directory):
os.mkdir(migrations_directory)
init_path = os.path.join(migrations_directory, "__init__.py")
if not os.path.isfile(init_path):
open(init_path, "w").close()
with open(writer.path, "w") as fh:
fh.write(writer.as_string())

View File

@ -41,10 +41,10 @@ class MigrationAutodetector(object):
self.add_to_migration(
app_label,
operations.CreateModel(
model_state.name,
model_state.fields,
model_state.options,
model_state.bases,
name = model_state.name,
fields = model_state.fields,
options = model_state.options,
bases = model_state.bases,
)
)
# Removing models

View File

@ -37,7 +37,8 @@ class MigrationLoader(object):
self.disk_migrations = None
self.applied_migrations = None
def migration_module(self, app_label):
@classmethod
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)
@ -52,7 +53,7 @@ class MigrationLoader(object):
for app in cache.get_apps():
# Get the migrations module directory
app_label = app.__name__.split(".")[-2]
module_name = self.migration_module(app_label)
module_name = self.migrations_module(app_label)
try:
module = import_module(module_name)
except ImportError as e:

View File

@ -54,3 +54,9 @@ class Operation(object):
drop the model's table.
"""
raise NotImplementedError()
def describe(self):
"""
Outputs a brief summary of what the action does.
"""
return "%s: %s" % (self.__class__.__name__, self._constructor_args)

View File

@ -23,6 +23,9 @@ class AddField(Operation):
from_model = from_state.render().get_model(app_label, self.model_name)
schema_editor.remove_field(from_model, from_model._meta.get_field_by_name(self.name)[0])
def describe(self):
return "Add field %s to %s" % (self.name, self.model_name)
class RemoveField(Operation):
"""
@ -48,3 +51,6 @@ class RemoveField(Operation):
from_model = from_state.render().get_model(app_label, self.model_name)
to_model = to_state.render().get_model(app_label, self.model_name)
schema_editor.add_field(from_model, to_model._meta.get_field_by_name(self.name)[0])
def describe(self):
return "Remove field %s from %s" % (self.name, self.model_name)

View File

@ -25,6 +25,9 @@ class CreateModel(Operation):
app_cache = from_state.render()
schema_editor.delete_model(app_cache.get_model(app, self.name))
def describe(self):
return "Create model %s" % (self.name, )
class DeleteModel(Operation):
"""
@ -44,3 +47,6 @@ class DeleteModel(Operation):
def database_backwards(self, app_label, schema_editor, from_state, to_state):
app_cache = to_state.render()
schema_editor.create_model(app_cache.get_model(app_label, self.name))
def describe(self):
return "Delete model %s" % (self.name, )

View File

@ -1,8 +1,12 @@
from __future__ import unicode_literals
import datetime
import types
import os
from django.utils import six
from django.utils.importlib import import_module
from django.db import models
from django.db.models.loading import cache
from django.db.migrations.loader import MigrationLoader
class MigrationWriter(object):
@ -49,6 +53,24 @@ class MigrationWriter(object):
def filename(self):
return "%s.py" % self.migration.name
@property
def path(self):
migrations_module_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
try:
migrations_module = import_module(migrations_module_name)
basedir = os.path.dirname(migrations_module.__file__)
except ImportError:
# 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])
else:
raise ImportError("Cannot open migrations module %s for app %s" % (migrations_module_name, self.migration.app_label))
return os.path.join(basedir, self.filename)
@classmethod
def serialize(cls, value):
"""
@ -130,6 +152,17 @@ class MigrationWriter(object):
if module is None:
raise ValueError("Cannot serialize function %r: No module" % value)
return "%s.%s" % (module, value.__name__), set(["import %s" % module])
# Classes
elif isinstance(value, type):
special_cases = [
(models.Model, "models.Model", []),
]
for case, string, imports in special_cases:
if case is value:
return string, set(imports)
if hasattr(value, "__module__"):
module = value.__module__
return "%s.%s" % (module, value.__name__), set(["import %s" % module])
# Uh oh.
else:
raise ValueError("Cannot serialize: %r" % value)