Anonymous avatar Anonymous committed 1b3e618

Magical migration creation situations!

Comments (0)

Files changed (2)

             "null": True,
             "related_to": None,
             "default": None,
+            "primary": False,
         }
         if isinstance(column, (list, tuple)):
             try:
                     "null": 4,
                     "related_to": 5,
                     "default": 6,
+                    "primary": 7,
                 }[name]]
             except IndexError:
                 return defaults[name]
         self.execute('DROP TABLE %s;' % params)
 
 
-    def add_column(self, table_name, column_name, type_name, type_param=None, unique=False, null=True, related_to=None, default=None):
+    def add_column(self, table_name, column_name, type_name, type_param=None, unique=False, null=True, related_to=None, default=None, primary=False):
         """
         Adds the column 'column_name' to the table 'table_name'.
         The column will have type 'type_name', which is one of the generic
         @param unique: Whether this column has UNIQUE set. Defaults to False.
         @param null: If this column will be allowed to contain NULL values. Defaults to True.
         @param related_to: A tuple of (table_name, column_name) for the column this references if it is a ForeignKey.
+        @param primary: If this is the primary key column
         """
         qn = connection.ops.quote_name
         sql, sqlparams = self.column_sql(column_name, type_name, type_param, unique, null, related_to)
         self.execute(sql, sqlparams)
 
 
-    def column_sql(self, column_name, type_name, type_param=None, unique=False, null=True, related_to=None, default=None):
+    def column_sql(self, column_name, type_name, type_param=None, unique=False, null=True, related_to=None, default=None, primary=False):
         """
         Creates the SQL snippet for a column. Used by add_column and add_table.
         """

management/commands/startmigration.py

     option_list = BaseCommand.option_list
     help = "Creates a new template migration for the given app"
 
-    def handle(self, app=None, name="", **options):
+    def handle(self, app=None, name="", model=None, **options):
         if not app:
             print "Please provide an app in which to create the migration."
             return
         # See if the app exists
         try:
-            app_module = __import__(app, {}, {}, ['migrations'])
+            app_module = __import__(app, {}, {}, ['migrations','models'])
         except ImportError:
             print "App '%s' doesn't seem to exist." % app
             return
+        # If there's a model, open it and have a poke
+        if model:
+            try:
+                model = getattr(app_module.models, model)
+                print model
+            except AttributeError:
+                print "The specified model '%s' doesn't seem to exist." % model
         # Make the migrations directory if it's not there
         migrations_dir = os.path.join(
             os.path.dirname(app_module.__file__),
             "".join([random.choice(string.letters.lower()) for i in range(0)]), # Possible random stuff insertion
             name,
         )
+        # If there's a model, make the migration skeleton, else leave it bare
+        if model:
+            table_name = model._meta.db_table
+            fields = []
+            for f in model._meta.local_fields:
+                # We use a list of tuples to get nice ordering
+                field = [
+                    ("name", f.column),
+                    ("null", f.null),
+                ]
+                type, type_param = genericify_type(f.db_type())
+                field.append(("type", type))
+                field.append(("type_param", type_param))
+                if f.primary_key:
+                    field.append(('primary', True))
+                if f.unique:
+                    field.append(('unique', True))
+                if f.rel:
+                    field.append(('related_to', (
+                        f.rel.to._meta.db_table,
+                        f.rel.to._meta.get_field(f.rel.field_name).column,
+                    )))
+                fields.append(field)
+            forwards = '''db.create_table("%s", [
+            %s
+        ])''' % (
+                table_name,
+                ",\n            ".join([
+                    "{%s}" % ", ".join("%r: %r" % (x, y) for x, y in f)
+                    for f in fields
+                ]),
+            )
+            backwards = '''db.delete_table("%s")''' % table_name
+        else:
+            forwards = '"Write your forwards migration here"'
+            backwards = '"Write your backwards migration here"'
         fp = open(os.path.join(migrations_dir, new_filename), "w")
         fp.write("""
 from south.db import db
 class Migration:
     
     def forwards(self):
-        # Write your forwards migration here
-        pass
+        %s
     
     def backwards(self):
-        # Write your backwards migration here
-        pass""" % app)
+        %s
+""" % (app, forwards, backwards))
         fp.close()
+
+
+def genericify_type(typestr):
+    if "(" not in typestr:
+        type = typestr
+        param = None
+    else:
+        type, param = typestr.split("(")
+        param = param[:-1]
+    # Make sure it doesn't need to be mapped back to a more generic type
+    type = {
+        "varchar": "string",
+    }.get(type, type)
+    return type, param
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.