1
0
mirror of https://github.com/django/django.git synced 2025-03-11 01:42:35 +00:00

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 sys
import os
from optparse import make_option from optparse import make_option
from django.core.management.base import BaseCommand 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.loader import MigrationLoader
from django.db.migrations.autodetector import MigrationAutodetector, InteractiveMigrationQuestioner from django.db.migrations.autodetector import MigrationAutodetector, InteractiveMigrationQuestioner
from django.db.migrations.state import ProjectState from django.db.migrations.state import ProjectState
from django.db.migrations.writer import MigrationWriter
from django.db.models.loading import cache from django.db.models.loading import cache
@ -49,4 +51,30 @@ class Command(BaseCommand):
if app_labels: if app_labels:
changes = autodetector.trim_to_apps(changes, 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( self.add_to_migration(
app_label, app_label,
operations.CreateModel( operations.CreateModel(
model_state.name, name = model_state.name,
model_state.fields, fields = model_state.fields,
model_state.options, options = model_state.options,
model_state.bases, bases = model_state.bases,
) )
) )
# Removing models # Removing models

View File

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

View File

@ -54,3 +54,9 @@ class Operation(object):
drop the model's table. drop the model's table.
""" """
raise NotImplementedError() 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) 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]) 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): class RemoveField(Operation):
""" """
@ -48,3 +51,6 @@ class RemoveField(Operation):
from_model = from_state.render().get_model(app_label, self.model_name) from_model = from_state.render().get_model(app_label, self.model_name)
to_model = to_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]) 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() app_cache = from_state.render()
schema_editor.delete_model(app_cache.get_model(app, self.name)) schema_editor.delete_model(app_cache.get_model(app, self.name))
def describe(self):
return "Create model %s" % (self.name, )
class DeleteModel(Operation): class DeleteModel(Operation):
""" """
@ -44,3 +47,6 @@ class DeleteModel(Operation):
def database_backwards(self, app_label, schema_editor, from_state, to_state): def database_backwards(self, app_label, schema_editor, from_state, to_state):
app_cache = to_state.render() app_cache = to_state.render()
schema_editor.create_model(app_cache.get_model(app_label, self.name)) 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 from __future__ import unicode_literals
import datetime import datetime
import types import types
import os
from django.utils import six from django.utils import six
from django.utils.importlib import import_module
from django.db import models from django.db import models
from django.db.models.loading import cache
from django.db.migrations.loader import MigrationLoader
class MigrationWriter(object): class MigrationWriter(object):
@ -49,6 +53,24 @@ class MigrationWriter(object):
def filename(self): def filename(self):
return "%s.py" % self.migration.name 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 @classmethod
def serialize(cls, value): def serialize(cls, value):
""" """
@ -130,6 +152,17 @@ class MigrationWriter(object):
if module is None: if module is None:
raise ValueError("Cannot serialize function %r: No module" % value) raise ValueError("Cannot serialize function %r: No module" % value)
return "%s.%s" % (module, value.__name__), set(["import %s" % module]) 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. # Uh oh.
else: else:
raise ValueError("Cannot serialize: %r" % value) raise ValueError("Cannot serialize: %r" % value)