root / env / lib / python2.7 / site-packages / south / management / commands / datamigration.py @ d1a4905f
History | View | Annotate | Download (4.4 KB)
1 |
"""
|
---|---|
2 |
Data migration creation command
|
3 |
"""
|
4 |
|
5 |
import sys |
6 |
import os |
7 |
import re |
8 |
from optparse import make_option |
9 |
|
10 |
try:
|
11 |
set
|
12 |
except NameError: |
13 |
from sets import Set as set |
14 |
|
15 |
from django.core.management.base import BaseCommand |
16 |
from django.core.management.color import no_style |
17 |
from django.db import models |
18 |
from django.conf import settings |
19 |
|
20 |
from south.migration import Migrations |
21 |
from south.exceptions import NoMigrations |
22 |
from south.creator import freezer |
23 |
|
24 |
class Command(BaseCommand): |
25 |
option_list = BaseCommand.option_list + ( |
26 |
make_option('--freeze', action='append', dest='freeze_list', type='string', |
27 |
help='Freeze the specified app(s). Provide an app name with each; use the option multiple times for multiple apps'),
|
28 |
make_option('--stdout', action='store_true', dest='stdout', default=False, |
29 |
help='Print the migration to stdout instead of writing it to a file.'),
|
30 |
) |
31 |
help = "Creates a new template data migration for the given app"
|
32 |
usage_str = "Usage: ./manage.py datamigration appname migrationname [--stdout] [--freeze appname]"
|
33 |
|
34 |
def handle(self, app=None, name="", freeze_list=None, stdout=False, verbosity=1, **options): |
35 |
|
36 |
# Any supposed lists that are None become empty lists
|
37 |
freeze_list = freeze_list or []
|
38 |
|
39 |
# --stdout means name = -
|
40 |
if stdout:
|
41 |
name = "-"
|
42 |
|
43 |
# Only allow valid names
|
44 |
if re.search('[^_\w]', name) and name != "-": |
45 |
self.error("Migration names should contain only alphanumeric characters and underscores.") |
46 |
|
47 |
# if not name, there's an error
|
48 |
if not name: |
49 |
self.error("You must provide a name for this migration\n" + self.usage_str) |
50 |
|
51 |
if not app: |
52 |
self.error("You must provide an app to create a migration for.\n" + self.usage_str) |
53 |
|
54 |
# Get the Migrations for this app (creating the migrations dir if needed)
|
55 |
migrations = Migrations(app, force_creation=True, verbose_creation=verbosity > 0) |
56 |
|
57 |
# See what filename is next in line. We assume they use numbers.
|
58 |
new_filename = migrations.next_filename(name) |
59 |
|
60 |
# Work out which apps to freeze
|
61 |
apps_to_freeze = self.calc_frozen_apps(migrations, freeze_list)
|
62 |
|
63 |
# So, what's in this file, then?
|
64 |
file_contents = MIGRATION_TEMPLATE % { |
65 |
"frozen_models": freezer.freeze_apps_to_string(apps_to_freeze),
|
66 |
"complete_apps": apps_to_freeze and "complete_apps = [%s]" % (", ".join(map(repr, apps_to_freeze))) or "" |
67 |
} |
68 |
|
69 |
# - is a special name which means 'print to stdout'
|
70 |
if name == "-": |
71 |
print file_contents
|
72 |
# Write the migration file if the name isn't -
|
73 |
else:
|
74 |
fp = open(os.path.join(migrations.migrations_dir(), new_filename), "w") |
75 |
fp.write(file_contents) |
76 |
fp.close() |
77 |
print >>sys.stderr, "Created %s." % new_filename |
78 |
|
79 |
def calc_frozen_apps(self, migrations, freeze_list): |
80 |
"""
|
81 |
Works out, from the current app, settings, and the command line options,
|
82 |
which apps should be frozen.
|
83 |
"""
|
84 |
apps_to_freeze = [] |
85 |
for to_freeze in freeze_list: |
86 |
if "." in to_freeze: |
87 |
self.error("You cannot freeze %r; you must provide an app label, like 'auth' or 'books'." % to_freeze) |
88 |
# Make sure it's a real app
|
89 |
if not models.get_app(to_freeze): |
90 |
self.error("You cannot freeze %r; it's not an installed app." % to_freeze) |
91 |
# OK, it's fine
|
92 |
apps_to_freeze.append(to_freeze) |
93 |
if getattr(settings, 'SOUTH_AUTO_FREEZE_APP', True): |
94 |
apps_to_freeze.append(migrations.app_label()) |
95 |
return apps_to_freeze
|
96 |
|
97 |
def error(self, message, code=1): |
98 |
"""
|
99 |
Prints the error, and exits with the given code.
|
100 |
"""
|
101 |
print >>sys.stderr, message
|
102 |
sys.exit(code) |
103 |
|
104 |
|
105 |
MIGRATION_TEMPLATE = """# -*- coding: utf-8 -*-
|
106 |
import datetime
|
107 |
from south.db import db
|
108 |
from south.v2 import DataMigration
|
109 |
from django.db import models
|
110 |
|
111 |
class Migration(DataMigration):
|
112 |
|
113 |
def forwards(self, orm):
|
114 |
"Write your forwards methods here."
|
115 |
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
|
116 |
|
117 |
def backwards(self, orm):
|
118 |
"Write your backwards methods here."
|
119 |
|
120 |
models = %(frozen_models)s
|
121 |
|
122 |
%(complete_apps)s
|
123 |
symmetrical = True
|
124 |
"""
|