web/lib/django/core/management/commands/syncdb.py
changeset 0 0d40e90630ef
child 29 cc9b7e14412b
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 from django.core.management.base import NoArgsCommand
       
     2 from django.core.management.color import no_style
       
     3 from django.utils.importlib import import_module
       
     4 from optparse import make_option
       
     5 import sys
       
     6 
       
     7 try:
       
     8     set
       
     9 except NameError:
       
    10     from sets import Set as set   # Python 2.3 fallback
       
    11 
       
    12 class Command(NoArgsCommand):
       
    13     option_list = NoArgsCommand.option_list + (
       
    14         make_option('--noinput', action='store_false', dest='interactive', default=True,
       
    15             help='Tells Django to NOT prompt the user for input of any kind.'),
       
    16     )
       
    17     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
       
    18 
       
    19     def handle_noargs(self, **options):
       
    20         from django.db import connection, transaction, models
       
    21         from django.conf import settings
       
    22         from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal
       
    23 
       
    24         verbosity = int(options.get('verbosity', 1))
       
    25         interactive = options.get('interactive')
       
    26         show_traceback = options.get('traceback', False)
       
    27 
       
    28         self.style = no_style()
       
    29 
       
    30         # Import the 'management' module within each installed app, to register
       
    31         # dispatcher events.
       
    32         for app_name in settings.INSTALLED_APPS:
       
    33             try:
       
    34                 import_module('.management', app_name)
       
    35             except ImportError, exc:
       
    36                 # This is slightly hackish. We want to ignore ImportErrors
       
    37                 # if the "management" module itself is missing -- but we don't
       
    38                 # want to ignore the exception if the management module exists
       
    39                 # but raises an ImportError for some reason. The only way we
       
    40                 # can do this is to check the text of the exception. Note that
       
    41                 # we're a bit broad in how we check the text, because different
       
    42                 # Python implementations may not use the same text.
       
    43                 # CPython uses the text "No module named management"
       
    44                 # PyPy uses "No module named myproject.myapp.management"
       
    45                 msg = exc.args[0]
       
    46                 if not msg.startswith('No module named') or 'management' not in msg:
       
    47                     raise
       
    48 
       
    49         cursor = connection.cursor()
       
    50 
       
    51         # Get a list of already installed *models* so that references work right.
       
    52         tables = connection.introspection.table_names()
       
    53         seen_models = connection.introspection.installed_models(tables)
       
    54         created_models = set()
       
    55         pending_references = {}
       
    56 
       
    57         # Create the tables for each model
       
    58         for app in models.get_apps():
       
    59             app_name = app.__name__.split('.')[-2]
       
    60             model_list = models.get_models(app)
       
    61             for model in model_list:
       
    62                 # Create the model's database table, if it doesn't already exist.
       
    63                 if verbosity >= 2:
       
    64                     print "Processing %s.%s model" % (app_name, model._meta.object_name)
       
    65                 if connection.introspection.table_name_converter(model._meta.db_table) in tables:
       
    66                     continue
       
    67                 sql, references = connection.creation.sql_create_model(model, self.style, seen_models)
       
    68                 seen_models.add(model)
       
    69                 created_models.add(model)
       
    70                 for refto, refs in references.items():
       
    71                     pending_references.setdefault(refto, []).extend(refs)
       
    72                     if refto in seen_models:
       
    73                         sql.extend(connection.creation.sql_for_pending_references(refto, self.style, pending_references))
       
    74                 sql.extend(connection.creation.sql_for_pending_references(model, self.style, pending_references))
       
    75                 if verbosity >= 1 and sql:
       
    76                     print "Creating table %s" % model._meta.db_table
       
    77                 for statement in sql:
       
    78                     cursor.execute(statement)
       
    79                 tables.append(connection.introspection.table_name_converter(model._meta.db_table))
       
    80 
       
    81         # Create the m2m tables. This must be done after all tables have been created
       
    82         # to ensure that all referred tables will exist.
       
    83         for app in models.get_apps():
       
    84             app_name = app.__name__.split('.')[-2]
       
    85             model_list = models.get_models(app)
       
    86             for model in model_list:
       
    87                 if model in created_models:
       
    88                     sql = connection.creation.sql_for_many_to_many(model, self.style)
       
    89                     if sql:
       
    90                         if verbosity >= 2:
       
    91                             print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)
       
    92                         for statement in sql:
       
    93                             cursor.execute(statement)
       
    94 
       
    95         transaction.commit_unless_managed()
       
    96 
       
    97         # Send the post_syncdb signal, so individual apps can do whatever they need
       
    98         # to do at this point.
       
    99         emit_post_sync_signal(created_models, verbosity, interactive)
       
   100 
       
   101         # The connection may have been closed by a syncdb handler.
       
   102         cursor = connection.cursor()
       
   103 
       
   104         # Install custom SQL for the app (but only if this
       
   105         # is a model we've just created)
       
   106         for app in models.get_apps():
       
   107             app_name = app.__name__.split('.')[-2]
       
   108             for model in models.get_models(app):
       
   109                 if model in created_models:
       
   110                     custom_sql = custom_sql_for_model(model, self.style)
       
   111                     if custom_sql:
       
   112                         if verbosity >= 1:
       
   113                             print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name)
       
   114                         try:
       
   115                             for sql in custom_sql:
       
   116                                 cursor.execute(sql)
       
   117                         except Exception, e:
       
   118                             sys.stderr.write("Failed to install custom SQL for %s.%s model: %s\n" % \
       
   119                                                 (app_name, model._meta.object_name, e))
       
   120                             if show_traceback:
       
   121                                 import traceback
       
   122                                 traceback.print_exc()
       
   123                             transaction.rollback_unless_managed()
       
   124                         else:
       
   125                             transaction.commit_unless_managed()
       
   126                     else:
       
   127                         if verbosity >= 2:
       
   128                             print "No custom SQL for %s.%s model" % (app_name, model._meta.object_name)
       
   129         # Install SQL indicies for all newly created models
       
   130         for app in models.get_apps():
       
   131             app_name = app.__name__.split('.')[-2]
       
   132             for model in models.get_models(app):
       
   133                 if model in created_models:
       
   134                     index_sql = connection.creation.sql_indexes_for_model(model, self.style)
       
   135                     if index_sql:
       
   136                         if verbosity >= 1:
       
   137                             print "Installing index for %s.%s model" % (app_name, model._meta.object_name)
       
   138                         try:
       
   139                             for sql in index_sql:
       
   140                                 cursor.execute(sql)
       
   141                         except Exception, e:
       
   142                             sys.stderr.write("Failed to install index for %s.%s model: %s\n" % \
       
   143                                                 (app_name, model._meta.object_name, e))
       
   144                             transaction.rollback_unless_managed()
       
   145                         else:
       
   146                             transaction.commit_unless_managed()
       
   147 
       
   148         # Install the 'initial_data' fixture, using format discovery
       
   149         from django.core.management import call_command
       
   150         call_command('loaddata', 'initial_data', verbosity=verbosity)