|
1 from django.core.management.base import NoArgsCommand |
|
2 from django.core.management.color import no_style |
|
3 from optparse import make_option |
|
4 import sys |
|
5 |
|
6 try: |
|
7 set |
|
8 except NameError: |
|
9 from sets import Set as set # Python 2.3 fallback |
|
10 |
|
11 class Command(NoArgsCommand): |
|
12 option_list = NoArgsCommand.option_list + ( |
|
13 make_option('--verbosity', action='store', dest='verbosity', default='1', |
|
14 type='choice', choices=['0', '1', '2'], |
|
15 help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), |
|
16 make_option('--noinput', action='store_false', dest='interactive', default=True, |
|
17 help='Tells Django to NOT prompt the user for input of any kind.'), |
|
18 ) |
|
19 help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." |
|
20 |
|
21 def handle_noargs(self, **options): |
|
22 from django.db import connection, transaction, models |
|
23 from django.conf import settings |
|
24 from django.core.management.sql import table_names, installed_models, sql_model_create, sql_for_pending_references, many_to_many_sql_for_model, custom_sql_for_model, sql_indexes_for_model, emit_post_sync_signal |
|
25 |
|
26 verbosity = int(options.get('verbosity', 1)) |
|
27 interactive = options.get('interactive') |
|
28 |
|
29 self.style = no_style() |
|
30 |
|
31 # Import the 'management' module within each installed app, to register |
|
32 # dispatcher events. |
|
33 for app_name in settings.INSTALLED_APPS: |
|
34 try: |
|
35 __import__(app_name + '.management', {}, {}, ['']) |
|
36 except ImportError, exc: |
|
37 if not exc.args[0].startswith('No module named management'): |
|
38 raise |
|
39 |
|
40 cursor = connection.cursor() |
|
41 |
|
42 if connection.features.uses_case_insensitive_names: |
|
43 table_name_converter = lambda x: x.upper() |
|
44 else: |
|
45 table_name_converter = lambda x: x |
|
46 # Get a list of all existing database tables, so we know what needs to |
|
47 # be added. |
|
48 tables = [table_name_converter(name) for name in table_names()] |
|
49 |
|
50 # Get a list of already installed *models* so that references work right. |
|
51 seen_models = installed_models(tables) |
|
52 created_models = set() |
|
53 pending_references = {} |
|
54 |
|
55 # Create the tables for each model |
|
56 for app in models.get_apps(): |
|
57 app_name = app.__name__.split('.')[-2] |
|
58 model_list = models.get_models(app) |
|
59 for model in model_list: |
|
60 # Create the model's database table, if it doesn't already exist. |
|
61 if verbosity >= 2: |
|
62 print "Processing %s.%s model" % (app_name, model._meta.object_name) |
|
63 if table_name_converter(model._meta.db_table) in tables: |
|
64 continue |
|
65 sql, references = sql_model_create(model, self.style, seen_models) |
|
66 seen_models.add(model) |
|
67 created_models.add(model) |
|
68 for refto, refs in references.items(): |
|
69 pending_references.setdefault(refto, []).extend(refs) |
|
70 if refto in seen_models: |
|
71 sql.extend(sql_for_pending_references(refto, self.style, pending_references)) |
|
72 sql.extend(sql_for_pending_references(model, self.style, pending_references)) |
|
73 if verbosity >= 1: |
|
74 print "Creating table %s" % model._meta.db_table |
|
75 for statement in sql: |
|
76 cursor.execute(statement) |
|
77 tables.append(table_name_converter(model._meta.db_table)) |
|
78 |
|
79 # Create the m2m tables. This must be done after all tables have been created |
|
80 # to ensure that all referred tables will exist. |
|
81 for app in models.get_apps(): |
|
82 app_name = app.__name__.split('.')[-2] |
|
83 model_list = models.get_models(app) |
|
84 for model in model_list: |
|
85 if model in created_models: |
|
86 sql = many_to_many_sql_for_model(model, self.style) |
|
87 if sql: |
|
88 if verbosity >= 2: |
|
89 print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name) |
|
90 for statement in sql: |
|
91 cursor.execute(statement) |
|
92 |
|
93 transaction.commit_unless_managed() |
|
94 |
|
95 # Send the post_syncdb signal, so individual apps can do whatever they need |
|
96 # to do at this point. |
|
97 emit_post_sync_signal(created_models, verbosity, interactive) |
|
98 |
|
99 # Install custom SQL for the app (but only if this |
|
100 # is a model we've just created) |
|
101 for app in models.get_apps(): |
|
102 app_name = app.__name__.split('.')[-2] |
|
103 for model in models.get_models(app): |
|
104 if model in created_models: |
|
105 custom_sql = custom_sql_for_model(model) |
|
106 if custom_sql: |
|
107 if verbosity >= 1: |
|
108 print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name) |
|
109 try: |
|
110 for sql in custom_sql: |
|
111 cursor.execute(sql) |
|
112 except Exception, e: |
|
113 sys.stderr.write("Failed to install custom SQL for %s.%s model: %s" % \ |
|
114 (app_name, model._meta.object_name, e)) |
|
115 transaction.rollback_unless_managed() |
|
116 else: |
|
117 transaction.commit_unless_managed() |
|
118 |
|
119 # Install SQL indicies for all newly created models |
|
120 for app in models.get_apps(): |
|
121 app_name = app.__name__.split('.')[-2] |
|
122 for model in models.get_models(app): |
|
123 if model in created_models: |
|
124 index_sql = sql_indexes_for_model(model, self.style) |
|
125 if index_sql: |
|
126 if verbosity >= 1: |
|
127 print "Installing index for %s.%s model" % (app_name, model._meta.object_name) |
|
128 try: |
|
129 for sql in index_sql: |
|
130 cursor.execute(sql) |
|
131 except Exception, e: |
|
132 sys.stderr.write("Failed to install index for %s.%s model: %s" % \ |
|
133 (app_name, model._meta.object_name, e)) |
|
134 transaction.rollback_unless_managed() |
|
135 else: |
|
136 transaction.commit_unless_managed() |
|
137 |
|
138 # Install the 'initial_data' fixture, using format discovery |
|
139 from django.core.management import call_command |
|
140 call_command('loaddata', 'initial_data', verbosity=verbosity) |