app/django/core/management/commands/syncdb.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     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)