web/lib/django/core/management/commands/syncdb.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     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
     1 from optparse import make_option
     5 import sys
     2 import sys
     6 
     3 
     7 try:
     4 from django.conf import settings
     8     set
     5 from django.core.management.base import NoArgsCommand
     9 except NameError:
     6 from django.core.management.color import no_style
    10     from sets import Set as set   # Python 2.3 fallback
     7 from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal
       
     8 from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
       
     9 from django.utils.datastructures import SortedDict
       
    10 from django.utils.importlib import import_module
       
    11 
    11 
    12 
    12 class Command(NoArgsCommand):
    13 class Command(NoArgsCommand):
    13     option_list = NoArgsCommand.option_list + (
    14     option_list = NoArgsCommand.option_list + (
    14         make_option('--noinput', action='store_false', dest='interactive', default=True,
    15         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             help='Tells Django to NOT prompt the user for input of any kind.'),
       
    17         make_option('--database', action='store', dest='database',
       
    18             default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. '
       
    19                 'Defaults to the "default" database.'),
    16     )
    20     )
    17     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
    21     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
    18 
    22 
    19     def handle_noargs(self, **options):
    23     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 
    24         verbosity = int(options.get('verbosity', 1))
    25         verbosity = int(options.get('verbosity', 1))
    25         interactive = options.get('interactive')
    26         interactive = options.get('interactive')
    26         show_traceback = options.get('traceback', False)
    27         show_traceback = options.get('traceback', False)
    27 
    28 
    44                 # PyPy uses "No module named myproject.myapp.management"
    45                 # PyPy uses "No module named myproject.myapp.management"
    45                 msg = exc.args[0]
    46                 msg = exc.args[0]
    46                 if not msg.startswith('No module named') or 'management' not in msg:
    47                 if not msg.startswith('No module named') or 'management' not in msg:
    47                     raise
    48                     raise
    48 
    49 
       
    50         db = options.get('database', DEFAULT_DB_ALIAS)
       
    51         connection = connections[db]
    49         cursor = connection.cursor()
    52         cursor = connection.cursor()
    50 
    53 
    51         # Get a list of already installed *models* so that references work right.
    54         # Get a list of already installed *models* so that references work right.
    52         tables = connection.introspection.table_names()
    55         tables = connection.introspection.table_names()
    53         seen_models = connection.introspection.installed_models(tables)
    56         seen_models = connection.introspection.installed_models(tables)
    54         created_models = set()
    57         created_models = set()
    55         pending_references = {}
    58         pending_references = {}
    56 
    59 
       
    60         # Build the manifest of apps and models that are to be synchronized
       
    61         all_models = [
       
    62             (app.__name__.split('.')[-2],
       
    63                 [m for m in models.get_models(app, include_auto_created=True)
       
    64                 if router.allow_syncdb(db, m)])
       
    65             for app in models.get_apps()
       
    66         ]
       
    67         def model_installed(model):
       
    68             opts = model._meta
       
    69             converter = connection.introspection.table_name_converter
       
    70             return not ((converter(opts.db_table) in tables) or
       
    71                 (opts.auto_created and converter(opts.auto_created._meta.db_table) in tables))
       
    72 
       
    73         manifest = SortedDict(
       
    74             (app_name, filter(model_installed, model_list))
       
    75             for app_name, model_list in all_models
       
    76         )
       
    77 
    57         # Create the tables for each model
    78         # Create the tables for each model
    58         for app in models.get_apps():
    79         for app_name, model_list in manifest.items():
    59             app_name = app.__name__.split('.')[-2]
       
    60             model_list = models.get_models(app)
       
    61             for model in model_list:
    80             for model in model_list:
    62                 # Create the model's database table, if it doesn't already exist.
    81                 # Create the model's database table, if it doesn't already exist.
    63                 if verbosity >= 2:
    82                 if verbosity >= 2:
    64                     print "Processing %s.%s model" % (app_name, model._meta.object_name)
    83                     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)
    84                 sql, references = connection.creation.sql_create_model(model, self.style, seen_models)
    68                 seen_models.add(model)
    85                 seen_models.add(model)
    69                 created_models.add(model)
    86                 created_models.add(model)
    70                 for refto, refs in references.items():
    87                 for refto, refs in references.items():
    71                     pending_references.setdefault(refto, []).extend(refs)
    88                     pending_references.setdefault(refto, []).extend(refs)
    76                     print "Creating table %s" % model._meta.db_table
    93                     print "Creating table %s" % model._meta.db_table
    77                 for statement in sql:
    94                 for statement in sql:
    78                     cursor.execute(statement)
    95                     cursor.execute(statement)
    79                 tables.append(connection.introspection.table_name_converter(model._meta.db_table))
    96                 tables.append(connection.introspection.table_name_converter(model._meta.db_table))
    80 
    97 
    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 
    98 
    95         transaction.commit_unless_managed()
    99         transaction.commit_unless_managed(using=db)
    96 
   100 
    97         # Send the post_syncdb signal, so individual apps can do whatever they need
   101         # Send the post_syncdb signal, so individual apps can do whatever they need
    98         # to do at this point.
   102         # to do at this point.
    99         emit_post_sync_signal(created_models, verbosity, interactive)
   103         emit_post_sync_signal(created_models, verbosity, interactive, db)
   100 
   104 
   101         # The connection may have been closed by a syncdb handler.
   105         # The connection may have been closed by a syncdb handler.
   102         cursor = connection.cursor()
   106         cursor = connection.cursor()
   103 
   107 
   104         # Install custom SQL for the app (but only if this
   108         # Install custom SQL for the app (but only if this
   105         # is a model we've just created)
   109         # is a model we've just created)
   106         for app in models.get_apps():
   110         for app_name, model_list in manifest.items():
   107             app_name = app.__name__.split('.')[-2]
   111             for model in model_list:
   108             for model in models.get_models(app):
       
   109                 if model in created_models:
   112                 if model in created_models:
   110                     custom_sql = custom_sql_for_model(model, self.style)
   113                     custom_sql = custom_sql_for_model(model, self.style, connection)
   111                     if custom_sql:
   114                     if custom_sql:
   112                         if verbosity >= 1:
   115                         if verbosity >= 1:
   113                             print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name)
   116                             print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name)
   114                         try:
   117                         try:
   115                             for sql in custom_sql:
   118                             for sql in custom_sql:
   118                             sys.stderr.write("Failed to install custom SQL for %s.%s model: %s\n" % \
   121                             sys.stderr.write("Failed to install custom SQL for %s.%s model: %s\n" % \
   119                                                 (app_name, model._meta.object_name, e))
   122                                                 (app_name, model._meta.object_name, e))
   120                             if show_traceback:
   123                             if show_traceback:
   121                                 import traceback
   124                                 import traceback
   122                                 traceback.print_exc()
   125                                 traceback.print_exc()
   123                             transaction.rollback_unless_managed()
   126                             transaction.rollback_unless_managed(using=db)
   124                         else:
   127                         else:
   125                             transaction.commit_unless_managed()
   128                             transaction.commit_unless_managed(using=db)
   126                     else:
   129                     else:
   127                         if verbosity >= 2:
   130                         if verbosity >= 2:
   128                             print "No custom SQL for %s.%s model" % (app_name, model._meta.object_name)
   131                             print "No custom SQL for %s.%s model" % (app_name, model._meta.object_name)
       
   132 
   129         # Install SQL indicies for all newly created models
   133         # Install SQL indicies for all newly created models
   130         for app in models.get_apps():
   134         for app_name, model_list in manifest.items():
   131             app_name = app.__name__.split('.')[-2]
   135             for model in model_list:
   132             for model in models.get_models(app):
       
   133                 if model in created_models:
   136                 if model in created_models:
   134                     index_sql = connection.creation.sql_indexes_for_model(model, self.style)
   137                     index_sql = connection.creation.sql_indexes_for_model(model, self.style)
   135                     if index_sql:
   138                     if index_sql:
   136                         if verbosity >= 1:
   139                         if verbosity >= 1:
   137                             print "Installing index for %s.%s model" % (app_name, model._meta.object_name)
   140                             print "Installing index for %s.%s model" % (app_name, model._meta.object_name)
   139                             for sql in index_sql:
   142                             for sql in index_sql:
   140                                 cursor.execute(sql)
   143                                 cursor.execute(sql)
   141                         except Exception, e:
   144                         except Exception, e:
   142                             sys.stderr.write("Failed to install index for %s.%s model: %s\n" % \
   145                             sys.stderr.write("Failed to install index for %s.%s model: %s\n" % \
   143                                                 (app_name, model._meta.object_name, e))
   146                                                 (app_name, model._meta.object_name, e))
   144                             transaction.rollback_unless_managed()
   147                             transaction.rollback_unless_managed(using=db)
   145                         else:
   148                         else:
   146                             transaction.commit_unless_managed()
   149                             transaction.commit_unless_managed(using=db)
   147 
   150 
   148         # Install the 'initial_data' fixture, using format discovery
       
   149         from django.core.management import call_command
   151         from django.core.management import call_command
   150         call_command('loaddata', 'initial_data', verbosity=verbosity)
   152         call_command('loaddata', 'initial_data', verbosity=verbosity, database=db)