thirdparty/google_appengine/lib/django/django/core/management.py
changeset 109 620f9b141567
child 2864 2e0b0af889be
equal deleted inserted replaced
108:261778de26ff 109:620f9b141567
       
     1 # Django management-related functions, including "CREATE TABLE" generation and
       
     2 # development-server initialization.
       
     3 
       
     4 import django
       
     5 from django.core.exceptions import ImproperlyConfigured
       
     6 import os, re, shutil, sys, textwrap
       
     7 from optparse import OptionParser
       
     8 from django.utils import termcolors
       
     9 
       
    10 # For Python 2.3
       
    11 if not hasattr(__builtins__, 'set'):
       
    12     from sets import Set as set
       
    13 
       
    14 MODULE_TEMPLATE = '''    {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%}
       
    15     <tr>
       
    16         <th>{%% if perms.%(app)s.%(changeperm)s %%}<a href="%(app)s/%(mod)s/">{%% endif %%}%(name)s{%% if perms.%(app)s.%(changeperm)s %%}</a>{%% endif %%}</th>
       
    17         <td class="x50">{%% if perms.%(app)s.%(addperm)s %%}<a href="%(app)s/%(mod)s/add/" class="addlink">{%% endif %%}Add{%% if perms.%(app)s.%(addperm)s %%}</a>{%% endif %%}</td>
       
    18         <td class="x75">{%% if perms.%(app)s.%(changeperm)s %%}<a href="%(app)s/%(mod)s/" class="changelink">{%% endif %%}Change{%% if perms.%(app)s.%(changeperm)s %%}</a>{%% endif %%}</td>
       
    19     </tr>
       
    20     {%% endif %%}'''
       
    21 
       
    22 APP_ARGS = '[appname ...]'
       
    23 
       
    24 # Use django.__path__[0] because we don't know which directory django into
       
    25 # which has been installed.
       
    26 PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template')
       
    27 
       
    28 INVALID_PROJECT_NAMES = ('django', 'site', 'test')
       
    29 
       
    30 # Set up the terminal color scheme.
       
    31 class dummy: pass
       
    32 style = dummy()
       
    33 style.ERROR = termcolors.make_style(fg='red', opts=('bold',))
       
    34 style.ERROR_OUTPUT = termcolors.make_style(fg='red', opts=('bold',))
       
    35 style.NOTICE = termcolors.make_style(fg='red')
       
    36 style.SQL_FIELD = termcolors.make_style(fg='green', opts=('bold',))
       
    37 style.SQL_COLTYPE = termcolors.make_style(fg='green')
       
    38 style.SQL_KEYWORD = termcolors.make_style(fg='yellow')
       
    39 style.SQL_TABLE = termcolors.make_style(opts=('bold',))
       
    40 del dummy
       
    41 
       
    42 def disable_termcolors():
       
    43     class dummy:
       
    44         def __getattr__(self, attr):
       
    45             return lambda x: x
       
    46     global style
       
    47     style = dummy()
       
    48 
       
    49 # Disable terminal coloring on Windows, Pocket PC, or if somebody's piping the output.
       
    50 if sys.platform == 'win32' or sys.platform == 'Pocket PC' or not sys.stdout.isatty():
       
    51     disable_termcolors()
       
    52 
       
    53 def _is_valid_dir_name(s):
       
    54     return bool(re.search(r'^\w+$', s))
       
    55 
       
    56 def _get_installed_models(table_list):
       
    57     "Gets a set of all models that are installed, given a list of existing tables"
       
    58     from django.db import models
       
    59     all_models = []
       
    60     for app in models.get_apps():
       
    61         for model in models.get_models(app):
       
    62             all_models.append(model)
       
    63     return set([m for m in all_models if m._meta.db_table in table_list])
       
    64 
       
    65 def _get_table_list():
       
    66     "Gets a list of all db tables that are physically installed."
       
    67     from django.db import connection, get_introspection_module
       
    68     cursor = connection.cursor()
       
    69     return get_introspection_module().get_table_list(cursor)
       
    70 
       
    71 def _get_sequence_list():
       
    72     "Returns a list of information about all DB sequences for all models in all apps"
       
    73     from django.db import models
       
    74 
       
    75     apps = models.get_apps()
       
    76     sequence_list = []
       
    77 
       
    78     for app in apps:
       
    79         for model in models.get_models(app):
       
    80             for f in model._meta.fields:
       
    81                 if isinstance(f, models.AutoField):
       
    82                     sequence_list.append({'table':model._meta.db_table,'column':f.column,})
       
    83                     break # Only one AutoField is allowed per model, so don't bother continuing.
       
    84 
       
    85             for f in model._meta.many_to_many:
       
    86                 sequence_list.append({'table':f.m2m_db_table(),'column':None,})
       
    87 
       
    88     return sequence_list
       
    89 
       
    90 # If the foreign key points to an AutoField, a PositiveIntegerField or a
       
    91 # PositiveSmallIntegerField, the foreign key should be an IntegerField, not the
       
    92 # referred field type. Otherwise, the foreign key should be the same type of
       
    93 # field as the field to which it points.
       
    94 get_rel_data_type = lambda f: (f.get_internal_type() in ('AutoField', 'PositiveIntegerField', 'PositiveSmallIntegerField')) and 'IntegerField' or f.get_internal_type()
       
    95 
       
    96 def get_version():
       
    97     "Returns the version as a human-format string."
       
    98     from django import VERSION
       
    99     v = '.'.join([str(i) for i in VERSION[:-1]])
       
   100     if VERSION[-1]:
       
   101         v += '-' + VERSION[-1]
       
   102     return v
       
   103 
       
   104 def get_sql_create(app):
       
   105     "Returns a list of the CREATE TABLE SQL statements for the given app."
       
   106     from django.db import get_creation_module, models
       
   107     data_types = get_creation_module().DATA_TYPES
       
   108 
       
   109     if not data_types:
       
   110         # This must be the "dummy" database backend, which means the user
       
   111         # hasn't set DATABASE_ENGINE.
       
   112         sys.stderr.write(style.ERROR("Error: Django doesn't know which syntax to use for your SQL statements,\n" +
       
   113             "because you haven't specified the DATABASE_ENGINE setting.\n" +
       
   114             "Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n"))
       
   115         sys.exit(1)
       
   116 
       
   117     # Get installed models, so we generate REFERENCES right.
       
   118     # We trim models from the current app so that the sqlreset command does not
       
   119     # generate invalid SQL (leaving models out of known_models is harmless, so
       
   120     # we can be conservative).
       
   121     app_models = models.get_models(app)
       
   122     final_output = []
       
   123     known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models])
       
   124     pending_references = {}
       
   125 
       
   126     for model in app_models:
       
   127         output, references = _get_sql_model_create(model, known_models)
       
   128         final_output.extend(output)
       
   129         for refto, refs in references.items():
       
   130             pending_references.setdefault(refto,[]).extend(refs)
       
   131         final_output.extend(_get_sql_for_pending_references(model, pending_references))
       
   132         # Keep track of the fact that we've created the table for this model.
       
   133         known_models.add(model)
       
   134 
       
   135     # Create the many-to-many join tables.
       
   136     for model in app_models:
       
   137         final_output.extend(_get_many_to_many_sql_for_model(model))
       
   138 
       
   139     # Handle references to tables that are from other apps
       
   140     # but don't exist physically
       
   141     not_installed_models = set(pending_references.keys())
       
   142     if not_installed_models:
       
   143         alter_sql = []
       
   144         for model in not_installed_models:
       
   145             alter_sql.extend(['-- ' + sql for sql in
       
   146                 _get_sql_for_pending_references(model, pending_references)])
       
   147         if alter_sql:
       
   148             final_output.append('-- The following references should be added but depend on non-existent tables:')
       
   149             final_output.extend(alter_sql)
       
   150 
       
   151     return final_output
       
   152 get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)."
       
   153 get_sql_create.args = APP_ARGS
       
   154 
       
   155 def _get_sql_model_create(model, known_models=set()):
       
   156     """
       
   157     Get the SQL required to create a single model.
       
   158 
       
   159     Returns list_of_sql, pending_references_dict
       
   160     """
       
   161     from django.db import backend, get_creation_module, models
       
   162     data_types = get_creation_module().DATA_TYPES
       
   163 
       
   164     opts = model._meta
       
   165     final_output = []
       
   166     table_output = []
       
   167     pending_references = {}
       
   168     for f in opts.fields:
       
   169         if isinstance(f, (models.ForeignKey, models.OneToOneField)):
       
   170             rel_field = f.rel.get_related_field()
       
   171             data_type = get_rel_data_type(rel_field)
       
   172         else:
       
   173             rel_field = f
       
   174             data_type = f.get_internal_type()
       
   175         col_type = data_types[data_type]
       
   176         if col_type is not None:
       
   177             # Make the definition (e.g. 'foo VARCHAR(30)') for this field.
       
   178             field_output = [style.SQL_FIELD(backend.quote_name(f.column)),
       
   179                 style.SQL_COLTYPE(col_type % rel_field.__dict__)]
       
   180             field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')))
       
   181             if f.unique:
       
   182                 field_output.append(style.SQL_KEYWORD('UNIQUE'))
       
   183             if f.primary_key:
       
   184                 field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
       
   185             if f.rel:
       
   186                 if f.rel.to in known_models:
       
   187                     field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
       
   188                         style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)) + ' (' + \
       
   189                         style.SQL_FIELD(backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' + 
       
   190                         backend.get_deferrable_sql()
       
   191                     )
       
   192                 else:
       
   193                     # We haven't yet created the table to which this field
       
   194                     # is related, so save it for later.
       
   195                     pr = pending_references.setdefault(f.rel.to, []).append((model, f))
       
   196             table_output.append(' '.join(field_output))
       
   197     if opts.order_with_respect_to:
       
   198         table_output.append(style.SQL_FIELD(backend.quote_name('_order')) + ' ' + \
       
   199             style.SQL_COLTYPE(data_types['IntegerField']) + ' ' + \
       
   200             style.SQL_KEYWORD('NULL'))
       
   201     for field_constraints in opts.unique_together:
       
   202         table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \
       
   203             ", ".join([backend.quote_name(style.SQL_FIELD(opts.get_field(f).column)) for f in field_constraints]))
       
   204 
       
   205     full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(backend.quote_name(opts.db_table)) + ' (']
       
   206     for i, line in enumerate(table_output): # Combine and add commas.
       
   207         full_statement.append('    %s%s' % (line, i < len(table_output)-1 and ',' or ''))
       
   208     full_statement.append(');')
       
   209     final_output.append('\n'.join(full_statement))
       
   210 
       
   211     return final_output, pending_references
       
   212 
       
   213 def _get_sql_for_pending_references(model, pending_references):
       
   214     """
       
   215     Get any ALTER TABLE statements to add constraints after the fact.
       
   216     """
       
   217     from django.db import backend, get_creation_module
       
   218     data_types = get_creation_module().DATA_TYPES
       
   219 
       
   220     final_output = []
       
   221     if backend.supports_constraints:
       
   222         opts = model._meta
       
   223         if model in pending_references:
       
   224             for rel_class, f in pending_references[model]:
       
   225                 rel_opts = rel_class._meta
       
   226                 r_table = rel_opts.db_table
       
   227                 r_col = f.column
       
   228                 table = opts.db_table
       
   229                 col = opts.get_field(f.rel.field_name).column
       
   230                 # For MySQL, r_name must be unique in the first 64 characters.
       
   231                 # So we are careful with character usage here.
       
   232                 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
       
   233                 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \
       
   234                     (backend.quote_name(r_table), r_name,
       
   235                     backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col), 
       
   236                     backend.get_deferrable_sql()))
       
   237             del pending_references[model]
       
   238     return final_output
       
   239 
       
   240 def _get_many_to_many_sql_for_model(model):
       
   241     from django.db import backend, get_creation_module
       
   242     from django.db.models import GenericRel
       
   243 
       
   244     data_types = get_creation_module().DATA_TYPES
       
   245 
       
   246     opts = model._meta
       
   247     final_output = []
       
   248     for f in opts.many_to_many:
       
   249         if not isinstance(f.rel, GenericRel):
       
   250             table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \
       
   251                 style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' (']
       
   252             table_output.append('    %s %s %s,' % \
       
   253                 (style.SQL_FIELD(backend.quote_name('id')),
       
   254                 style.SQL_COLTYPE(data_types['AutoField']),
       
   255                 style.SQL_KEYWORD('NOT NULL PRIMARY KEY')))
       
   256             table_output.append('    %s %s %s %s (%s)%s,' % \
       
   257                 (style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
       
   258                 style.SQL_COLTYPE(data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__),
       
   259                 style.SQL_KEYWORD('NOT NULL REFERENCES'),
       
   260                 style.SQL_TABLE(backend.quote_name(opts.db_table)),
       
   261                 style.SQL_FIELD(backend.quote_name(opts.pk.column)),
       
   262                 backend.get_deferrable_sql()))
       
   263             table_output.append('    %s %s %s %s (%s)%s,' % \
       
   264                 (style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())),
       
   265                 style.SQL_COLTYPE(data_types[get_rel_data_type(f.rel.to._meta.pk)] % f.rel.to._meta.pk.__dict__),
       
   266                 style.SQL_KEYWORD('NOT NULL REFERENCES'),
       
   267                 style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
       
   268                 style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)),
       
   269                 backend.get_deferrable_sql()))
       
   270             table_output.append('    %s (%s, %s)' % \
       
   271                 (style.SQL_KEYWORD('UNIQUE'),
       
   272                 style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
       
   273                 style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name()))))
       
   274             table_output.append(');')
       
   275             final_output.append('\n'.join(table_output))
       
   276     return final_output
       
   277 
       
   278 def get_sql_delete(app):
       
   279     "Returns a list of the DROP TABLE SQL statements for the given app."
       
   280     from django.db import backend, connection, models, get_introspection_module
       
   281     introspection = get_introspection_module()
       
   282 
       
   283     # This should work even if a connection isn't available
       
   284     try:
       
   285         cursor = connection.cursor()
       
   286     except:
       
   287         cursor = None
       
   288 
       
   289     # Figure out which tables already exist
       
   290     if cursor:
       
   291         table_names = introspection.get_table_list(cursor)
       
   292     else:
       
   293         table_names = []
       
   294 
       
   295     output = []
       
   296 
       
   297     # Output DROP TABLE statements for standard application tables.
       
   298     to_delete = set()
       
   299 
       
   300     references_to_delete = {}
       
   301     app_models = models.get_models(app)
       
   302     for model in app_models:
       
   303         if cursor and model._meta.db_table in table_names:
       
   304             # The table exists, so it needs to be dropped
       
   305             opts = model._meta
       
   306             for f in opts.fields:
       
   307                 if f.rel and f.rel.to not in to_delete:
       
   308                     references_to_delete.setdefault(f.rel.to, []).append( (model, f) )
       
   309 
       
   310             to_delete.add(model)
       
   311 
       
   312     for model in app_models:
       
   313         if cursor and model._meta.db_table in table_names:
       
   314             # Drop the table now
       
   315             output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'),
       
   316                 style.SQL_TABLE(backend.quote_name(model._meta.db_table))))
       
   317             if backend.supports_constraints and references_to_delete.has_key(model):
       
   318                 for rel_class, f in references_to_delete[model]:
       
   319                     table = rel_class._meta.db_table
       
   320                     col = f.column
       
   321                     r_table = model._meta.db_table
       
   322                     r_col = model._meta.get_field(f.rel.field_name).column
       
   323                     output.append('%s %s %s %s;' % \
       
   324                         (style.SQL_KEYWORD('ALTER TABLE'),
       
   325                         style.SQL_TABLE(backend.quote_name(table)),
       
   326                         style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
       
   327                         style.SQL_FIELD(backend.quote_name('%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table))))))))
       
   328                 del references_to_delete[model]
       
   329 
       
   330     # Output DROP TABLE statements for many-to-many tables.
       
   331     for model in app_models:
       
   332         opts = model._meta
       
   333         for f in opts.many_to_many:
       
   334             if cursor and f.m2m_db_table() in table_names:
       
   335                 output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'),
       
   336                     style.SQL_TABLE(backend.quote_name(f.m2m_db_table()))))
       
   337 
       
   338     app_label = app_models[0]._meta.app_label
       
   339 
       
   340     # Close database connection explicitly, in case this output is being piped
       
   341     # directly into a database client, to avoid locking issues.
       
   342     if cursor:
       
   343         cursor.close()
       
   344         connection.close()
       
   345 
       
   346     return output[::-1] # Reverse it, to deal with table dependencies.
       
   347 get_sql_delete.help_doc = "Prints the DROP TABLE SQL statements for the given app name(s)."
       
   348 get_sql_delete.args = APP_ARGS
       
   349 
       
   350 def get_sql_reset(app):
       
   351     "Returns a list of the DROP TABLE SQL, then the CREATE TABLE SQL, for the given module."
       
   352     return get_sql_delete(app) + get_sql_all(app)
       
   353 get_sql_reset.help_doc = "Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s)."
       
   354 get_sql_reset.args = APP_ARGS
       
   355 
       
   356 def get_sql_flush():
       
   357     "Returns a list of the SQL statements used to flush the database"
       
   358     from django.db import backend
       
   359     statements = backend.get_sql_flush(style, _get_table_list(), _get_sequence_list())
       
   360     return statements
       
   361 get_sql_flush.help_doc = "Returns a list of the SQL statements required to return all tables in the database to the state they were in just after they were installed."
       
   362 get_sql_flush.args = ''
       
   363 
       
   364 def get_custom_sql_for_model(model):
       
   365     from django.db import models
       
   366     from django.conf import settings
       
   367 
       
   368     opts = model._meta
       
   369     app_dir = os.path.normpath(os.path.join(os.path.dirname(models.get_app(model._meta.app_label).__file__), 'sql'))
       
   370     output = []
       
   371 
       
   372     # Some backends can't execute more than one SQL statement at a time,
       
   373     # so split into separate statements.
       
   374     statements = re.compile(r";[ \t]*$", re.M)
       
   375 
       
   376     # Find custom SQL, if it's available.
       
   377     sql_files = [os.path.join(app_dir, "%s.%s.sql" % (opts.object_name.lower(), settings.DATABASE_ENGINE)),
       
   378                  os.path.join(app_dir, "%s.sql" % opts.object_name.lower())]
       
   379     for sql_file in sql_files:
       
   380         if os.path.exists(sql_file):
       
   381             fp = open(sql_file, 'U')
       
   382             for statement in statements.split(fp.read()):
       
   383                 # Remove any comments from the file
       
   384                 statement = re.sub(r"--.*[\n\Z]", "", statement)
       
   385                 if statement.strip():
       
   386                     output.append(statement + ";")
       
   387             fp.close()
       
   388 
       
   389     return output
       
   390 
       
   391 def get_custom_sql(app):
       
   392     "Returns a list of the custom table modifying SQL statements for the given app."
       
   393     from django.db.models import get_models
       
   394     output = []
       
   395 
       
   396     app_models = get_models(app)
       
   397     app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql'))
       
   398 
       
   399     for model in app_models:
       
   400         output.extend(get_custom_sql_for_model(model))
       
   401 
       
   402     return output
       
   403 get_custom_sql.help_doc = "Prints the custom table modifying SQL statements for the given app name(s)."
       
   404 get_custom_sql.args = APP_ARGS
       
   405 
       
   406 def get_sql_initial_data(apps):
       
   407     "Returns a list of the initial INSERT SQL statements for the given app."
       
   408     return style.ERROR("This action has been renamed. Try './manage.py sqlcustom %s'." % ' '.join(apps and apps or ['app1', 'app2']))
       
   409 get_sql_initial_data.help_doc = "RENAMED: see 'sqlcustom'"
       
   410 get_sql_initial_data.args = ''
       
   411 
       
   412 def get_sql_sequence_reset(app):
       
   413     "Returns a list of the SQL statements to reset PostgreSQL sequences for the given app."
       
   414     from django.db import backend, models
       
   415     output = []
       
   416     for model in models.get_models(app):
       
   417         for f in model._meta.fields:
       
   418             if isinstance(f, models.AutoField):
       
   419                 output.append("%s setval('%s', (%s max(%s) %s %s));" % \
       
   420                     (style.SQL_KEYWORD('SELECT'),
       
   421                     style.SQL_FIELD('%s_%s_seq' % (model._meta.db_table, f.column)),
       
   422                     style.SQL_KEYWORD('SELECT'),
       
   423                     style.SQL_FIELD(backend.quote_name(f.column)),
       
   424                     style.SQL_KEYWORD('FROM'),
       
   425                     style.SQL_TABLE(backend.quote_name(model._meta.db_table))))
       
   426                 break # Only one AutoField is allowed per model, so don't bother continuing.
       
   427         for f in model._meta.many_to_many:
       
   428             output.append("%s setval('%s', (%s max(%s) %s %s));" % \
       
   429                 (style.SQL_KEYWORD('SELECT'),
       
   430                 style.SQL_FIELD('%s_id_seq' % f.m2m_db_table()),
       
   431                 style.SQL_KEYWORD('SELECT'),
       
   432                 style.SQL_FIELD(backend.quote_name('id')),
       
   433                 style.SQL_KEYWORD('FROM'),
       
   434                 style.SQL_TABLE(f.m2m_db_table())))
       
   435     return output
       
   436 get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given app name(s)."
       
   437 get_sql_sequence_reset.args = APP_ARGS
       
   438 
       
   439 def get_sql_indexes(app):
       
   440     "Returns a list of the CREATE INDEX SQL statements for all models in the given app."
       
   441     from django.db import models
       
   442     output = []
       
   443     for model in models.get_models(app):
       
   444         output.extend(get_sql_indexes_for_model(model))
       
   445     return output
       
   446 get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
       
   447 get_sql_indexes.args = APP_ARGS
       
   448 
       
   449 def get_sql_indexes_for_model(model):
       
   450     "Returns the CREATE INDEX SQL statements for a single model"
       
   451     from django.db import backend
       
   452     output = []
       
   453 
       
   454     for f in model._meta.fields:
       
   455         if f.db_index:
       
   456             unique = f.unique and 'UNIQUE ' or ''
       
   457             output.append(
       
   458                 style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
       
   459                 style.SQL_TABLE('%s_%s' % (model._meta.db_table, f.column)) + ' ' + \
       
   460                 style.SQL_KEYWORD('ON') + ' ' + \
       
   461                 style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
       
   462                 "(%s);" % style.SQL_FIELD(backend.quote_name(f.column))
       
   463             )
       
   464     return output
       
   465 
       
   466 def get_sql_all(app):
       
   467     "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
       
   468     return get_sql_create(app) + get_custom_sql(app) + get_sql_indexes(app)
       
   469 get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)."
       
   470 get_sql_all.args = APP_ARGS
       
   471 
       
   472 def _emit_post_sync_signal(created_models, verbosity, interactive):
       
   473     from django.db import models
       
   474     from django.dispatch import dispatcher
       
   475     # Emit the post_sync signal for every application.
       
   476     for app in models.get_apps():
       
   477         app_name = app.__name__.split('.')[-2]
       
   478         if verbosity >= 2:
       
   479             print "Running post-sync handlers for application", app_name
       
   480         dispatcher.send(signal=models.signals.post_syncdb, sender=app,
       
   481             app=app, created_models=created_models,
       
   482             verbosity=verbosity, interactive=interactive)
       
   483 
       
   484 def syncdb(verbosity=1, interactive=True):
       
   485     "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
       
   486     from django.db import connection, transaction, models, get_creation_module
       
   487     from django.conf import settings
       
   488 
       
   489     disable_termcolors()
       
   490 
       
   491     # First, try validating the models.
       
   492     _check_for_validation_errors()
       
   493 
       
   494     # Import the 'management' module within each installed app, to register
       
   495     # dispatcher events.
       
   496     for app_name in settings.INSTALLED_APPS:
       
   497         try:
       
   498             __import__(app_name + '.management', {}, {}, [''])
       
   499         except ImportError:
       
   500             pass
       
   501 
       
   502     data_types = get_creation_module().DATA_TYPES
       
   503 
       
   504     cursor = connection.cursor()
       
   505 
       
   506     # Get a list of all existing database tables,
       
   507     # so we know what needs to be added.
       
   508     table_list = _get_table_list()
       
   509 
       
   510     # Get a list of already installed *models* so that references work right.
       
   511     seen_models = _get_installed_models(table_list)
       
   512     created_models = set()
       
   513     pending_references = {}
       
   514 
       
   515     # Create the tables for each model
       
   516     for app in models.get_apps():
       
   517         app_name = app.__name__.split('.')[-2]
       
   518         model_list = models.get_models(app)
       
   519         for model in model_list:
       
   520             # Create the model's database table, if it doesn't already exist.
       
   521             if verbosity >= 2:
       
   522                 print "Processing %s.%s model" % (app_name, model._meta.object_name)
       
   523             if model._meta.db_table in table_list:
       
   524                 continue
       
   525             sql, references = _get_sql_model_create(model, seen_models)
       
   526             seen_models.add(model)
       
   527             created_models.add(model)
       
   528             for refto, refs in references.items():
       
   529                 pending_references.setdefault(refto, []).extend(refs)
       
   530             sql.extend(_get_sql_for_pending_references(model, pending_references))
       
   531             if verbosity >= 1:
       
   532                 print "Creating table %s" % model._meta.db_table
       
   533             for statement in sql:
       
   534                 cursor.execute(statement)
       
   535             table_list.append(model._meta.db_table)
       
   536 
       
   537     # Create the m2m tables. This must be done after all tables have been created
       
   538     # to ensure that all referred tables will exist.
       
   539     for app in models.get_apps():
       
   540         app_name = app.__name__.split('.')[-2]
       
   541         model_list = models.get_models(app)
       
   542         for model in model_list:
       
   543             if model in created_models:
       
   544                 sql = _get_many_to_many_sql_for_model(model)
       
   545                 if sql:
       
   546                     if verbosity >= 2:
       
   547                         print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name)
       
   548                     for statement in sql:
       
   549                         cursor.execute(statement)
       
   550 
       
   551     transaction.commit_unless_managed()
       
   552 
       
   553     # Send the post_syncdb signal, so individual apps can do whatever they need
       
   554     # to do at this point.
       
   555     _emit_post_sync_signal(created_models, verbosity, interactive)
       
   556 
       
   557     # Install custom SQL for the app (but only if this 
       
   558     # is a model we've just created)
       
   559     for app in models.get_apps():
       
   560         for model in models.get_models(app):
       
   561             if model in created_models:
       
   562                 custom_sql = get_custom_sql_for_model(model)
       
   563                 if custom_sql:
       
   564                     if verbosity >= 1:
       
   565                         print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name)
       
   566                     try:
       
   567                         for sql in custom_sql:
       
   568                             cursor.execute(sql)
       
   569                     except Exception, e:
       
   570                         sys.stderr.write("Failed to install custom SQL for %s.%s model: %s" % \
       
   571                                             (app_name, model._meta.object_name, e))
       
   572                         transaction.rollback_unless_managed()
       
   573                     else:
       
   574                         transaction.commit_unless_managed()
       
   575 
       
   576     # Install SQL indicies for all newly created models
       
   577     for app in models.get_apps():
       
   578         app_name = app.__name__.split('.')[-2]
       
   579         for model in models.get_models(app):
       
   580             if model in created_models:
       
   581                 index_sql = get_sql_indexes_for_model(model)
       
   582                 if index_sql:
       
   583                     if verbosity >= 1:
       
   584                         print "Installing index for %s.%s model" % (app_name, model._meta.object_name)
       
   585                     try:
       
   586                         for sql in index_sql:
       
   587                             cursor.execute(sql)
       
   588                     except Exception, e:
       
   589                         sys.stderr.write("Failed to install index for %s.%s model: %s" % \
       
   590                                             (app_name, model._meta.object_name, e))
       
   591                         transaction.rollback_unless_managed()
       
   592                     else:
       
   593                         transaction.commit_unless_managed()
       
   594 
       
   595     # Install the 'initialdata' fixture, using format discovery
       
   596     load_data(['initial_data'], verbosity=verbosity)
       
   597 syncdb.help_doc = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
       
   598 syncdb.args = '[--verbosity] [--interactive]'
       
   599 
       
   600 def get_admin_index(app):
       
   601     "Returns admin-index template snippet (in list form) for the given app."
       
   602     from django.utils.text import capfirst
       
   603     from django.db.models import get_models
       
   604     output = []
       
   605     app_models = get_models(app)
       
   606     app_label = app_models[0]._meta.app_label
       
   607     output.append('{%% if perms.%s %%}' % app_label)
       
   608     output.append('<div class="module"><h2>%s</h2><table>' % app_label.title())
       
   609     for model in app_models:
       
   610         if model._meta.admin:
       
   611             output.append(MODULE_TEMPLATE % {
       
   612                 'app': app_label,
       
   613                 'mod': model._meta.module_name,
       
   614                 'name': capfirst(model._meta.verbose_name_plural),
       
   615                 'addperm': model._meta.get_add_permission(),
       
   616                 'changeperm': model._meta.get_change_permission(),
       
   617             })
       
   618     output.append('</table></div>')
       
   619     output.append('{% endif %}')
       
   620     return output
       
   621 get_admin_index.help_doc = "Prints the admin-index template snippet for the given app name(s)."
       
   622 get_admin_index.args = APP_ARGS
       
   623 
       
   624 def _module_to_dict(module, omittable=lambda k: k.startswith('_')):
       
   625     "Converts a module namespace to a Python dictionary. Used by get_settings_diff."
       
   626     return dict([(k, repr(v)) for k, v in module.__dict__.items() if not omittable(k)])
       
   627 
       
   628 def diffsettings():
       
   629     """
       
   630     Displays differences between the current settings.py and Django's
       
   631     default settings. Settings that don't appear in the defaults are
       
   632     followed by "###".
       
   633     """
       
   634     # Inspired by Postfix's "postconf -n".
       
   635     from django.conf import settings, global_settings
       
   636 
       
   637     user_settings = _module_to_dict(settings._target)
       
   638     default_settings = _module_to_dict(global_settings)
       
   639 
       
   640     output = []
       
   641     keys = user_settings.keys()
       
   642     keys.sort()
       
   643     for key in keys:
       
   644         if key not in default_settings:
       
   645             output.append("%s = %s  ###" % (key, user_settings[key]))
       
   646         elif user_settings[key] != default_settings[key]:
       
   647             output.append("%s = %s" % (key, user_settings[key]))
       
   648     print '\n'.join(output)
       
   649 diffsettings.args = ""
       
   650 
       
   651 def reset(app, interactive=True):
       
   652     "Executes the equivalent of 'get_sql_reset' in the current database."
       
   653     from django.db import connection, transaction
       
   654     from django.conf import settings
       
   655     app_name = app.__name__.split('.')[-2]
       
   656 
       
   657     disable_termcolors()
       
   658 
       
   659     # First, try validating the models.
       
   660     _check_for_validation_errors(app)
       
   661     sql_list = get_sql_reset(app)
       
   662 
       
   663     if interactive:
       
   664         confirm = raw_input("""
       
   665 You have requested a database reset.
       
   666 This will IRREVERSIBLY DESTROY any data for
       
   667 the "%s" application in the database "%s".
       
   668 Are you sure you want to do this?
       
   669 
       
   670 Type 'yes' to continue, or 'no' to cancel: """ % (app_name, settings.DATABASE_NAME))
       
   671     else:
       
   672         confirm = 'yes'
       
   673 
       
   674     if confirm == 'yes':
       
   675         try:
       
   676             cursor = connection.cursor()
       
   677             for sql in sql_list:
       
   678                 cursor.execute(sql)
       
   679         except Exception, e:
       
   680             sys.stderr.write(style.ERROR("""Error: %s couldn't be reset. Possible reasons:
       
   681   * The database isn't running or isn't configured correctly.
       
   682   * At least one of the database tables doesn't exist.
       
   683   * The SQL was invalid.
       
   684 Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run.
       
   685 The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')
       
   686             transaction.rollback_unless_managed()
       
   687             sys.exit(1)
       
   688         transaction.commit_unless_managed()
       
   689     else:
       
   690         print "Reset cancelled."
       
   691 reset.help_doc = "Executes ``sqlreset`` for the given app(s) in the current database."
       
   692 reset.args = '[--interactive]' + APP_ARGS
       
   693 
       
   694 def flush(verbosity=1, interactive=True):
       
   695     "Returns all tables in the database to the same state they were in immediately after syncdb."
       
   696     from django.conf import settings
       
   697     from django.db import connection, transaction, models
       
   698     from django.dispatch import dispatcher
       
   699     
       
   700     disable_termcolors()
       
   701 
       
   702     # First, try validating the models.
       
   703     _check_for_validation_errors()
       
   704 
       
   705     # Import the 'management' module within each installed app, to register
       
   706     # dispatcher events.
       
   707     for app_name in settings.INSTALLED_APPS:
       
   708         try:
       
   709             __import__(app_name + '.management', {}, {}, [''])
       
   710         except ImportError:
       
   711             pass
       
   712     
       
   713     sql_list = get_sql_flush()
       
   714 
       
   715     if interactive:
       
   716         confirm = raw_input("""
       
   717 You have requested a flush of the database.
       
   718 This will IRREVERSIBLY DESTROY all data currently in the database,
       
   719 and return each table to the state it was in after syncdb.
       
   720 Are you sure you want to do this?
       
   721 
       
   722 Type 'yes' to continue, or 'no' to cancel: """)
       
   723     else:
       
   724         confirm = 'yes'
       
   725 
       
   726     if confirm == 'yes':
       
   727         try:
       
   728             cursor = connection.cursor()
       
   729             for sql in sql_list:
       
   730                 cursor.execute(sql)
       
   731         except Exception, e:
       
   732             sys.stderr.write(style.ERROR("""Error: Database %s couldn't be flushed. Possible reasons:
       
   733   * The database isn't running or isn't configured correctly.
       
   734   * At least one of the expected database tables doesn't exist.
       
   735   * The SQL was invalid.
       
   736 Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run.
       
   737 The full error: """ % settings.DATABASE_NAME + style.ERROR_OUTPUT(str(e)) + '\n'))
       
   738             transaction.rollback_unless_managed()
       
   739             sys.exit(1)
       
   740         transaction.commit_unless_managed()
       
   741 
       
   742         # Emit the post sync signal. This allows individual
       
   743         # applications to respond as if the database had been
       
   744         # sync'd from scratch.
       
   745         _emit_post_sync_signal(models.get_models(), verbosity, interactive)
       
   746         
       
   747         # Reinstall the initial_data fixture
       
   748         load_data(['initial_data'], verbosity=verbosity)
       
   749         
       
   750     else:
       
   751         print "Flush cancelled."
       
   752 flush.help_doc = "Executes ``sqlflush`` on the current database."
       
   753 flush.args = '[--verbosity] [--interactive]'
       
   754 
       
   755 def _start_helper(app_or_project, name, directory, other_name=''):
       
   756     other = {'project': 'app', 'app': 'project'}[app_or_project]
       
   757     if not _is_valid_dir_name(name):
       
   758         sys.stderr.write(style.ERROR("Error: %r is not a valid %s name. Please use only numbers, letters and underscores.\n" % (name, app_or_project)))
       
   759         sys.exit(1)
       
   760     top_dir = os.path.join(directory, name)
       
   761     try:
       
   762         os.mkdir(top_dir)
       
   763     except OSError, e:
       
   764         sys.stderr.write(style.ERROR("Error: %s\n" % e))
       
   765         sys.exit(1)
       
   766     template_dir = PROJECT_TEMPLATE_DIR % app_or_project
       
   767     for d, subdirs, files in os.walk(template_dir):
       
   768         relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name)
       
   769         if relative_dir:
       
   770             os.mkdir(os.path.join(top_dir, relative_dir))
       
   771         for i, subdir in enumerate(subdirs):
       
   772             if subdir.startswith('.'):
       
   773                 del subdirs[i]
       
   774         for f in files:
       
   775             if f.endswith('.pyc'):
       
   776                 continue
       
   777             path_old = os.path.join(d, f)
       
   778             path_new = os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name))
       
   779             fp_old = open(path_old, 'r')
       
   780             fp_new = open(path_new, 'w')
       
   781             fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
       
   782             fp_old.close()
       
   783             fp_new.close()
       
   784             try:
       
   785                 shutil.copymode(path_old, path_new)
       
   786             except OSError:
       
   787                 sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))
       
   788 
       
   789 def startproject(project_name, directory):
       
   790     "Creates a Django project for the given project_name in the given directory."
       
   791     from random import choice
       
   792     if project_name in INVALID_PROJECT_NAMES:
       
   793         sys.stderr.write(style.ERROR("Error: '%r' conflicts with the name of an existing Python module and cannot be used as a project name. Please try another name.\n" % project_name))
       
   794         sys.exit(1)
       
   795     _start_helper('project', project_name, directory)
       
   796     # Create a random SECRET_KEY hash, and put it in the main settings.
       
   797     main_settings_file = os.path.join(directory, project_name, 'settings.py')
       
   798     settings_contents = open(main_settings_file, 'r').read()
       
   799     fp = open(main_settings_file, 'w')
       
   800     secret_key = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
       
   801     settings_contents = re.sub(r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents)
       
   802     fp.write(settings_contents)
       
   803     fp.close()
       
   804 startproject.help_doc = "Creates a Django project directory structure for the given project name in the current directory."
       
   805 startproject.args = "[projectname]"
       
   806 
       
   807 def startapp(app_name, directory):
       
   808     "Creates a Django app for the given app_name in the given directory."
       
   809     # Determine the project_name a bit naively -- by looking at the name of
       
   810     # the parent directory.
       
   811     project_dir = os.path.normpath(os.path.join(directory, '..'))
       
   812     project_name = os.path.basename(project_dir)
       
   813     if app_name == os.path.basename(directory):
       
   814         sys.stderr.write(style.ERROR("Error: You cannot create an app with the same name (%r) as your project.\n" % app_name))
       
   815         sys.exit(1)
       
   816     _start_helper('app', app_name, directory, project_name)
       
   817 startapp.help_doc = "Creates a Django app directory structure for the given app name in the current directory."
       
   818 startapp.args = "[appname]"
       
   819 
       
   820 def inspectdb():
       
   821     "Generator that introspects the tables in the given database name and returns a Django model, one line at a time."
       
   822     from django.db import connection, get_introspection_module
       
   823     import keyword
       
   824 
       
   825     introspection_module = get_introspection_module()
       
   826 
       
   827     table2model = lambda table_name: table_name.title().replace('_', '')
       
   828 
       
   829     cursor = connection.cursor()
       
   830     yield "# This is an auto-generated Django model module."
       
   831     yield "# You'll have to do the following manually to clean this up:"
       
   832     yield "#     * Rearrange models' order"
       
   833     yield "#     * Make sure each model has one field with primary_key=True"
       
   834     yield "# Feel free to rename the models, but don't rename db_table values or field names."
       
   835     yield "#"
       
   836     yield "# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]'"
       
   837     yield "# into your database."
       
   838     yield ''
       
   839     yield 'from django.db import models'
       
   840     yield ''
       
   841     for table_name in introspection_module.get_table_list(cursor):
       
   842         yield 'class %s(models.Model):' % table2model(table_name)
       
   843         try:
       
   844             relations = introspection_module.get_relations(cursor, table_name)
       
   845         except NotImplementedError:
       
   846             relations = {}
       
   847         try:
       
   848             indexes = introspection_module.get_indexes(cursor, table_name)
       
   849         except NotImplementedError:
       
   850             indexes = {}
       
   851         for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)):
       
   852             att_name = row[0]
       
   853             comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
       
   854             extra_params = {}  # Holds Field parameters such as 'db_column'.
       
   855 
       
   856             if ' ' in att_name:
       
   857                 extra_params['db_column'] = att_name
       
   858                 att_name = att_name.replace(' ', '')
       
   859                 comment_notes.append('Field renamed to remove spaces.')
       
   860             if keyword.iskeyword(att_name):
       
   861                 extra_params['db_column'] = att_name
       
   862                 att_name += '_field'
       
   863                 comment_notes.append('Field renamed because it was a Python reserved word.')
       
   864 
       
   865             if relations.has_key(i):
       
   866                 rel_to = relations[i][1] == table_name and "'self'" or table2model(relations[i][1])
       
   867                 field_type = 'ForeignKey(%s' % rel_to
       
   868                 if att_name.endswith('_id'):
       
   869                     att_name = att_name[:-3]
       
   870                 else:
       
   871                     extra_params['db_column'] = att_name
       
   872             else:
       
   873                 try:
       
   874                     field_type = introspection_module.DATA_TYPES_REVERSE[row[1]]
       
   875                 except KeyError:
       
   876                     field_type = 'TextField'
       
   877                     comment_notes.append('This field type is a guess.')
       
   878 
       
   879                 # This is a hook for DATA_TYPES_REVERSE to return a tuple of
       
   880                 # (field_type, extra_params_dict).
       
   881                 if type(field_type) is tuple:
       
   882                     field_type, new_params = field_type
       
   883                     extra_params.update(new_params)
       
   884 
       
   885                 # Add maxlength for all CharFields.
       
   886                 if field_type == 'CharField' and row[3]:
       
   887                     extra_params['maxlength'] = row[3]
       
   888 
       
   889                 if field_type == 'FloatField':
       
   890                     extra_params['max_digits'] = row[4]
       
   891                     extra_params['decimal_places'] = row[5]
       
   892 
       
   893                 # Add primary_key and unique, if necessary.
       
   894                 column_name = extra_params.get('db_column', att_name)
       
   895                 if column_name in indexes:
       
   896                     if indexes[column_name]['primary_key']:
       
   897                         extra_params['primary_key'] = True
       
   898                     elif indexes[column_name]['unique']:
       
   899                         extra_params['unique'] = True
       
   900 
       
   901                 field_type += '('
       
   902 
       
   903             # Don't output 'id = meta.AutoField(primary_key=True)', because
       
   904             # that's assumed if it doesn't exist.
       
   905             if att_name == 'id' and field_type == 'AutoField(' and extra_params == {'primary_key': True}:
       
   906                 continue
       
   907 
       
   908             # Add 'null' and 'blank', if the 'null_ok' flag was present in the
       
   909             # table description.
       
   910             if row[6]: # If it's NULL...
       
   911                 extra_params['blank'] = True
       
   912                 if not field_type in ('TextField(', 'CharField('):
       
   913                     extra_params['null'] = True
       
   914 
       
   915             field_desc = '%s = models.%s' % (att_name, field_type)
       
   916             if extra_params:
       
   917                 if not field_desc.endswith('('):
       
   918                     field_desc += ', '
       
   919                 field_desc += ', '.join(['%s=%r' % (k, v) for k, v in extra_params.items()])
       
   920             field_desc += ')'
       
   921             if comment_notes:
       
   922                 field_desc += ' # ' + ' '.join(comment_notes)
       
   923             yield '    %s' % field_desc
       
   924         yield '    class Meta:'
       
   925         yield '        db_table = %r' % table_name
       
   926         yield ''
       
   927 inspectdb.help_doc = "Introspects the database tables in the given database and outputs a Django model module."
       
   928 inspectdb.args = ""
       
   929 
       
   930 class ModelErrorCollection:
       
   931     def __init__(self, outfile=sys.stdout):
       
   932         self.errors = []
       
   933         self.outfile = outfile
       
   934 
       
   935     def add(self, context, error):
       
   936         self.errors.append((context, error))
       
   937         self.outfile.write(style.ERROR("%s: %s\n" % (context, error)))
       
   938 
       
   939 def get_validation_errors(outfile, app=None):
       
   940     """
       
   941     Validates all models that are part of the specified app. If no app name is provided,
       
   942     validates all models of all installed apps. Writes errors, if any, to outfile.
       
   943     Returns number of errors.
       
   944     """
       
   945     from django.conf import settings
       
   946     from django.db import models, connection
       
   947     from django.db.models.loading import get_app_errors
       
   948     from django.db.models.fields.related import RelatedObject
       
   949 
       
   950     e = ModelErrorCollection(outfile)
       
   951 
       
   952     for (app_name, error) in get_app_errors().items():
       
   953         e.add(app_name, error)
       
   954 
       
   955     for cls in models.get_models(app):
       
   956         opts = cls._meta
       
   957 
       
   958         # Do field-specific validation.
       
   959         for f in opts.fields:
       
   960             if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
       
   961                 e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
       
   962             if isinstance(f, models.CharField) and f.maxlength in (None, 0):
       
   963                 e.add(opts, '"%s": CharFields require a "maxlength" attribute.' % f.name)
       
   964             if isinstance(f, models.FloatField):
       
   965                 if f.decimal_places is None:
       
   966                     e.add(opts, '"%s": FloatFields require a "decimal_places" attribute.' % f.name)
       
   967                 if f.max_digits is None:
       
   968                     e.add(opts, '"%s": FloatFields require a "max_digits" attribute.' % f.name)
       
   969             if isinstance(f, models.FileField) and not f.upload_to:
       
   970                 e.add(opts, '"%s": FileFields require an "upload_to" attribute.' % f.name)
       
   971             if isinstance(f, models.ImageField):
       
   972                 try:
       
   973                     from PIL import Image
       
   974                 except ImportError:
       
   975                     e.add(opts, '"%s": To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
       
   976             if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
       
   977                 e.add(opts, '"%s": prepopulate_from should be a list or tuple.' % f.name)
       
   978             if f.choices:
       
   979                 if not hasattr(f.choices, '__iter__'):
       
   980                     e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name)
       
   981                 else:
       
   982                     for c in f.choices:
       
   983                         if not type(c) in (tuple, list) or len(c) != 2:
       
   984                             e.add(opts, '"%s": "choices" should be a sequence of two-tuples.' % f.name)
       
   985             if f.db_index not in (None, True, False):
       
   986                 e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)
       
   987 
       
   988             # Check that maxlength <= 255 if using older MySQL versions.
       
   989             if settings.DATABASE_ENGINE == 'mysql':
       
   990                 db_version = connection.get_server_version()
       
   991                 if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255:
       
   992                     e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]])))
       
   993 
       
   994             # Check to see if the related field will clash with any
       
   995             # existing fields, m2m fields, m2m related objects or related objects
       
   996             if f.rel:
       
   997                 rel_opts = f.rel.to._meta
       
   998                 if f.rel.to not in models.get_models():
       
   999                     e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, rel_opts.object_name))
       
  1000 
       
  1001                 rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
       
  1002                 rel_query_name = f.related_query_name()
       
  1003                 for r in rel_opts.fields:
       
  1004                     if r.name == rel_name:
       
  1005                         e.add(opts, "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1006                     if r.name == rel_query_name:
       
  1007                         e.add(opts, "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1008                 for r in rel_opts.many_to_many:
       
  1009                     if r.name == rel_name:
       
  1010                         e.add(opts, "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1011                     if r.name == rel_query_name:
       
  1012                         e.add(opts, "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1013                 for r in rel_opts.get_all_related_many_to_many_objects():
       
  1014                     if r.get_accessor_name() == rel_name:
       
  1015                         e.add(opts, "Accessor for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1016                     if r.get_accessor_name() == rel_query_name:
       
  1017                         e.add(opts, "Reverse query name for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1018                 for r in rel_opts.get_all_related_objects():
       
  1019                     if r.field is not f:
       
  1020                         if r.get_accessor_name() == rel_name:
       
  1021                             e.add(opts, "Accessor for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1022                         if r.get_accessor_name() == rel_query_name:
       
  1023                             e.add(opts, "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1024 
       
  1025 
       
  1026         for i, f in enumerate(opts.many_to_many):
       
  1027             # Check to see if the related m2m field will clash with any
       
  1028             # existing fields, m2m fields, m2m related objects or related objects
       
  1029             rel_opts = f.rel.to._meta
       
  1030             if f.rel.to not in models.get_models():
       
  1031                 e.add(opts, "'%s' has m2m relation with model %s, which has not been installed" % (f.name, rel_opts.object_name))
       
  1032 
       
  1033             rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
       
  1034             rel_query_name = f.related_query_name()
       
  1035             # If rel_name is none, there is no reverse accessor.
       
  1036             # (This only occurs for symmetrical m2m relations to self).
       
  1037             # If this is the case, there are no clashes to check for this field, as
       
  1038             # there are no reverse descriptors for this field.
       
  1039             if rel_name is not None:
       
  1040                 for r in rel_opts.fields:
       
  1041                     if r.name == rel_name:
       
  1042                         e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1043                     if r.name == rel_query_name:
       
  1044                         e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1045                 for r in rel_opts.many_to_many:
       
  1046                     if r.name == rel_name:
       
  1047                         e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1048                     if r.name == rel_query_name:
       
  1049                         e.add(opts, "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
       
  1050                 for r in rel_opts.get_all_related_many_to_many_objects():
       
  1051                     if r.field is not f:
       
  1052                         if r.get_accessor_name() == rel_name:
       
  1053                             e.add(opts, "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1054                         if r.get_accessor_name() == rel_query_name:
       
  1055                             e.add(opts, "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1056                 for r in rel_opts.get_all_related_objects():
       
  1057                     if r.get_accessor_name() == rel_name:
       
  1058                         e.add(opts, "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1059                     if r.get_accessor_name() == rel_query_name:
       
  1060                         e.add(opts, "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name))
       
  1061 
       
  1062         # Check admin attribute.
       
  1063         if opts.admin is not None:
       
  1064             if not isinstance(opts.admin, models.AdminOptions):
       
  1065                 e.add(opts, '"admin" attribute, if given, must be set to a models.AdminOptions() instance.')
       
  1066             else:
       
  1067                 # list_display
       
  1068                 if not isinstance(opts.admin.list_display, (list, tuple)):
       
  1069                     e.add(opts, '"admin.list_display", if given, must be set to a list or tuple.')
       
  1070                 else:
       
  1071                     for fn in opts.admin.list_display:
       
  1072                         try:
       
  1073                             f = opts.get_field(fn)
       
  1074                         except models.FieldDoesNotExist:
       
  1075                             if not hasattr(cls, fn):
       
  1076                                 e.add(opts, '"admin.list_display" refers to %r, which isn\'t an attribute, method or property.' % fn)
       
  1077                         else:
       
  1078                             if isinstance(f, models.ManyToManyField):
       
  1079                                 e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn)
       
  1080                 # list_display_links
       
  1081                 if opts.admin.list_display_links and not opts.admin.list_display:
       
  1082                     e.add(opts, '"admin.list_display" must be defined for "admin.list_display_links" to be used.')
       
  1083                 if not isinstance(opts.admin.list_display_links, (list, tuple)):
       
  1084                     e.add(opts, '"admin.list_display_links", if given, must be set to a list or tuple.')
       
  1085                 else:
       
  1086                     for fn in opts.admin.list_display_links:
       
  1087                         try:
       
  1088                             f = opts.get_field(fn)
       
  1089                         except models.FieldDoesNotExist:
       
  1090                             if not hasattr(cls, fn):
       
  1091                                 e.add(opts, '"admin.list_display_links" refers to %r, which isn\'t an attribute, method or property.' % fn)
       
  1092                         if fn not in opts.admin.list_display:
       
  1093                             e.add(opts, '"admin.list_display_links" refers to %r, which is not defined in "admin.list_display".' % fn)
       
  1094                 # list_filter
       
  1095                 if not isinstance(opts.admin.list_filter, (list, tuple)):
       
  1096                     e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.')
       
  1097                 else:
       
  1098                     for fn in opts.admin.list_filter:
       
  1099                         try:
       
  1100                             f = opts.get_field(fn)
       
  1101                         except models.FieldDoesNotExist:
       
  1102                             e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
       
  1103                 # date_hierarchy
       
  1104                 if opts.admin.date_hierarchy:
       
  1105                     try:
       
  1106                         f = opts.get_field(opts.admin.date_hierarchy)
       
  1107                     except models.FieldDoesNotExist:
       
  1108                         e.add(opts, '"admin.date_hierarchy" refers to %r, which isn\'t a field.' % opts.admin.date_hierarchy)
       
  1109 
       
  1110         # Check ordering attribute.
       
  1111         if opts.ordering:
       
  1112             for field_name in opts.ordering:
       
  1113                 if field_name == '?': continue
       
  1114                 if field_name.startswith('-'):
       
  1115                     field_name = field_name[1:]
       
  1116                 if opts.order_with_respect_to and field_name == '_order':
       
  1117                     continue
       
  1118                 if '.' in field_name: continue # Skip ordering in the format 'table.field'.
       
  1119                 try:
       
  1120                     opts.get_field(field_name, many_to_many=False)
       
  1121                 except models.FieldDoesNotExist:
       
  1122                     e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)
       
  1123 
       
  1124         # Check core=True, if needed.
       
  1125         for related in opts.get_followed_related_objects():
       
  1126             if not related.edit_inline:
       
  1127                 continue
       
  1128             try:
       
  1129                 for f in related.opts.fields:
       
  1130                     if f.core:
       
  1131                         raise StopIteration
       
  1132                 e.add(related.opts, "At least one field in %s should have core=True, because it's being edited inline by %s.%s." % (related.opts.object_name, opts.module_name, opts.object_name))
       
  1133             except StopIteration:
       
  1134                 pass
       
  1135 
       
  1136         # Check unique_together.
       
  1137         for ut in opts.unique_together:
       
  1138             for field_name in ut:
       
  1139                 try:
       
  1140                     f = opts.get_field(field_name, many_to_many=True)
       
  1141                 except models.FieldDoesNotExist:
       
  1142                     e.add(opts, '"unique_together" refers to %s, a field that doesn\'t exist. Check your syntax.' % field_name)
       
  1143                 else:
       
  1144                     if isinstance(f.rel, models.ManyToManyRel):
       
  1145                         e.add(opts, '"unique_together" refers to %s. ManyToManyFields are not supported in unique_together.' % f.name)
       
  1146 
       
  1147     return len(e.errors)
       
  1148 
       
  1149 def validate(outfile=sys.stdout, silent_success=False):
       
  1150     "Validates all installed models."
       
  1151     try:
       
  1152         num_errors = get_validation_errors(outfile)
       
  1153         if silent_success and num_errors == 0:
       
  1154             return
       
  1155         outfile.write('%s error%s found.\n' % (num_errors, num_errors != 1 and 's' or ''))
       
  1156     except ImproperlyConfigured:
       
  1157         outfile.write("Skipping validation because things aren't configured properly.")
       
  1158 validate.args = ''
       
  1159 
       
  1160 def _check_for_validation_errors(app=None):
       
  1161     """Check that an app has no validation errors, and exit with errors if it does."""
       
  1162     try:
       
  1163         from cStringIO import StringIO
       
  1164     except ImportError:
       
  1165         from StringIO import StringIO
       
  1166     s = StringIO()
       
  1167     num_errors = get_validation_errors(s, app)
       
  1168     if num_errors:
       
  1169         if app:
       
  1170             sys.stderr.write(style.ERROR("Error: %s couldn't be installed, because there were errors in your model:\n" % app))
       
  1171         else:
       
  1172             sys.stderr.write(style.ERROR("Error: Couldn't install apps, because there were errors in one or more models:\n"))
       
  1173         s.seek(0)
       
  1174         sys.stderr.write(s.read())
       
  1175         sys.exit(1)
       
  1176 
       
  1177 def runserver(addr, port, use_reloader=True, admin_media_dir=''):
       
  1178     "Starts a lightweight Web server for development."
       
  1179     from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
       
  1180     from django.core.handlers.wsgi import WSGIHandler
       
  1181     if not addr:
       
  1182         addr = '127.0.0.1'
       
  1183     if not port.isdigit():
       
  1184         sys.stderr.write(style.ERROR("Error: %r is not a valid port number.\n" % port))
       
  1185         sys.exit(1)
       
  1186     quit_command = sys.platform == 'win32' and 'CTRL-BREAK' or 'CONTROL-C'
       
  1187     def inner_run():
       
  1188         from django.conf import settings
       
  1189         print "Validating models..."
       
  1190         validate()
       
  1191         print "\nDjango version %s, using settings %r" % (get_version(), settings.SETTINGS_MODULE)
       
  1192         print "Development server is running at http://%s:%s/" % (addr, port)
       
  1193         print "Quit the server with %s." % quit_command
       
  1194         try:
       
  1195             import django
       
  1196             path = admin_media_dir or django.__path__[0] + '/contrib/admin/media'
       
  1197             handler = AdminMediaHandler(WSGIHandler(), path)
       
  1198             run(addr, int(port), handler)
       
  1199         except WSGIServerException, e:
       
  1200             # Use helpful error messages instead of ugly tracebacks.
       
  1201             ERRORS = {
       
  1202                 13: "You don't have permission to access that port.",
       
  1203                 98: "That port is already in use.",
       
  1204                 99: "That IP address can't be assigned-to.",
       
  1205             }
       
  1206             try:
       
  1207                 error_text = ERRORS[e.args[0].args[0]]
       
  1208             except (AttributeError, KeyError):
       
  1209                 error_text = str(e)
       
  1210             sys.stderr.write(style.ERROR("Error: %s" % error_text) + '\n')
       
  1211             sys.exit(1)
       
  1212         except KeyboardInterrupt:
       
  1213             sys.exit(0)
       
  1214     if use_reloader:
       
  1215         from django.utils import autoreload
       
  1216         autoreload.main(inner_run)
       
  1217     else:
       
  1218         inner_run()
       
  1219 runserver.args = '[--noreload] [--adminmedia=ADMIN_MEDIA_PATH] [optional port number, or ipaddr:port]'
       
  1220 
       
  1221 def createcachetable(tablename):
       
  1222     "Creates the table needed to use the SQL cache backend"
       
  1223     from django.db import backend, connection, transaction, get_creation_module, models
       
  1224     data_types = get_creation_module().DATA_TYPES
       
  1225     fields = (
       
  1226         # "key" is a reserved word in MySQL, so use "cache_key" instead.
       
  1227         models.CharField(name='cache_key', maxlength=255, unique=True, primary_key=True),
       
  1228         models.TextField(name='value'),
       
  1229         models.DateTimeField(name='expires', db_index=True),
       
  1230     )
       
  1231     table_output = []
       
  1232     index_output = []
       
  1233     for f in fields:
       
  1234         field_output = [backend.quote_name(f.name), data_types[f.get_internal_type()] % f.__dict__]
       
  1235         field_output.append("%sNULL" % (not f.null and "NOT " or ""))
       
  1236         if f.unique:
       
  1237             field_output.append("UNIQUE")
       
  1238         if f.primary_key:
       
  1239             field_output.append("PRIMARY KEY")
       
  1240         if f.db_index:
       
  1241             unique = f.unique and "UNIQUE " or ""
       
  1242             index_output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \
       
  1243                 (unique, tablename, f.name, backend.quote_name(tablename),
       
  1244                 backend.quote_name(f.name)))
       
  1245         table_output.append(" ".join(field_output))
       
  1246     full_statement = ["CREATE TABLE %s (" % backend.quote_name(tablename)]
       
  1247     for i, line in enumerate(table_output):
       
  1248         full_statement.append('    %s%s' % (line, i < len(table_output)-1 and ',' or ''))
       
  1249     full_statement.append(');')
       
  1250     curs = connection.cursor()
       
  1251     curs.execute("\n".join(full_statement))
       
  1252     for statement in index_output:
       
  1253         curs.execute(statement)
       
  1254     transaction.commit_unless_managed()
       
  1255 createcachetable.args = "[tablename]"
       
  1256 
       
  1257 def run_shell(use_plain=False):
       
  1258     "Runs a Python interactive interpreter. Tries to use IPython, if it's available."
       
  1259     # XXX: (Temporary) workaround for ticket #1796: force early loading of all
       
  1260     # models from installed apps.
       
  1261     from django.db.models.loading import get_models
       
  1262     loaded_models = get_models()
       
  1263 
       
  1264     try:
       
  1265         if use_plain:
       
  1266             # Don't bother loading IPython, because the user wants plain Python.
       
  1267             raise ImportError
       
  1268         import IPython
       
  1269         # Explicitly pass an empty list as arguments, because otherwise IPython
       
  1270         # would use sys.argv from this script.
       
  1271         shell = IPython.Shell.IPShell(argv=[])
       
  1272         shell.mainloop()
       
  1273     except ImportError:
       
  1274         import code
       
  1275         try: # Try activating rlcompleter, because it's handy.
       
  1276             import readline
       
  1277         except ImportError:
       
  1278             pass
       
  1279         else:
       
  1280             # We don't have to wrap the following import in a 'try', because
       
  1281             # we already know 'readline' was imported successfully.
       
  1282             import rlcompleter
       
  1283             readline.parse_and_bind("tab:complete")
       
  1284         code.interact()
       
  1285 run_shell.args = '[--plain]'
       
  1286 
       
  1287 def dbshell():
       
  1288     "Runs the command-line client for the current DATABASE_ENGINE."
       
  1289     from django.db import runshell
       
  1290     runshell()
       
  1291 dbshell.args = ""
       
  1292 
       
  1293 def runfcgi(args):
       
  1294     "Runs this project as a FastCGI application. Requires flup."
       
  1295     from django.conf import settings
       
  1296     from django.utils import translation
       
  1297     # Activate the current language, because it won't get activated later.
       
  1298     try:
       
  1299         translation.activate(settings.LANGUAGE_CODE)
       
  1300     except AttributeError:
       
  1301         pass
       
  1302     from django.core.servers.fastcgi import runfastcgi
       
  1303     runfastcgi(args)
       
  1304 runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
       
  1305 
       
  1306 def test(app_labels, verbosity=1):
       
  1307     "Runs the test suite for the specified applications"
       
  1308     from django.conf import settings
       
  1309     from django.db.models import get_app, get_apps
       
  1310 
       
  1311     if len(app_labels) == 0:
       
  1312         app_list = get_apps()
       
  1313     else:
       
  1314         app_list = [get_app(app_label) for app_label in app_labels]
       
  1315 
       
  1316     test_path = settings.TEST_RUNNER.split('.')
       
  1317     # Allow for Python 2.5 relative paths
       
  1318     if len(test_path) > 1:
       
  1319         test_module_name = '.'.join(test_path[:-1])
       
  1320     else:
       
  1321         test_module_name = '.'
       
  1322     test_module = __import__(test_module_name, {}, {}, test_path[-1])
       
  1323     test_runner = getattr(test_module, test_path[-1])
       
  1324 
       
  1325     failures = test_runner(app_list, verbosity)
       
  1326     if failures:
       
  1327         sys.exit(failures)
       
  1328         
       
  1329 test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified'
       
  1330 test.args = '[--verbosity] ' + APP_ARGS
       
  1331 
       
  1332 def load_data(fixture_labels, verbosity=1):
       
  1333     "Installs the provided fixture file(s) as data in the database."
       
  1334     from django.db.models import get_apps
       
  1335     from django.core import serializers
       
  1336     from django.db import connection, transaction
       
  1337     from django.conf import settings
       
  1338     import sys
       
  1339      
       
  1340     # Keep a count of the installed objects and fixtures
       
  1341     count = [0,0]
       
  1342     
       
  1343     humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
       
  1344 
       
  1345     # Get a cursor (even though we don't need one yet). This has
       
  1346     # the side effect of initializing the test database (if 
       
  1347     # it isn't already initialized).
       
  1348     cursor = connection.cursor()
       
  1349     
       
  1350     # Start transaction management. All fixtures are installed in a 
       
  1351     # single transaction to ensure that all references are resolved.
       
  1352     transaction.commit_unless_managed()
       
  1353     transaction.enter_transaction_management()
       
  1354     transaction.managed(True)
       
  1355     
       
  1356     app_fixtures = [os.path.join(os.path.dirname(app.__file__),'fixtures') for app in get_apps()]
       
  1357     for fixture_label in fixture_labels:
       
  1358         if verbosity > 0:
       
  1359             print "Loading '%s' fixtures..." % fixture_label
       
  1360         for fixture_dir in app_fixtures + list(settings.FIXTURE_DIRS) + ['']:
       
  1361             if verbosity > 1:
       
  1362                 print "Checking %s for fixtures..." % humanize(fixture_dir)
       
  1363             parts = fixture_label.split('.')
       
  1364             if len(parts) == 1:
       
  1365                 fixture_name = fixture_label
       
  1366                 formats = serializers.get_serializer_formats()
       
  1367             else:
       
  1368                 fixture_name, format = '.'.join(parts[:-1]), parts[-1]
       
  1369                 formats = [format]
       
  1370 
       
  1371             label_found = False
       
  1372             for format in formats:
       
  1373                 serializer = serializers.get_serializer(format)
       
  1374                 if verbosity > 1:
       
  1375                     print "Trying %s for %s fixture '%s'..." % \
       
  1376                         (humanize(fixture_dir), format, fixture_name)
       
  1377                 try:
       
  1378                     full_path = os.path.join(fixture_dir, '.'.join([fixture_name, format]))
       
  1379                     fixture = open(full_path, 'r')
       
  1380                     if label_found:
       
  1381                         fixture.close()
       
  1382                         print style.ERROR("Multiple fixtures named '%s' in %s. Aborting." % 
       
  1383                             (fixture_name, humanize(fixture_dir)))
       
  1384                         transaction.rollback()
       
  1385                         transaction.leave_transaction_management()
       
  1386                         return
       
  1387                     else:
       
  1388                         count[1] += 1
       
  1389                         if verbosity > 0:
       
  1390                             print "Installing %s fixture '%s' from %s." % \
       
  1391                                 (format, fixture_name, humanize(fixture_dir))
       
  1392                         try:
       
  1393                             objects =  serializers.deserialize(format, fixture)
       
  1394                             for obj in objects:
       
  1395                                 count[0] += 1
       
  1396                                 obj.save()
       
  1397                             label_found = True
       
  1398                         except Exception, e:
       
  1399                             fixture.close()
       
  1400                             sys.stderr.write(
       
  1401                                 style.ERROR("Problem installing fixture '%s': %s\n" % 
       
  1402                                      (full_path, str(e))))
       
  1403                             transaction.rollback()
       
  1404                             transaction.leave_transaction_management()
       
  1405                             return
       
  1406                         fixture.close()
       
  1407                 except:
       
  1408                     if verbosity > 1:
       
  1409                         print "No %s fixture '%s' in %s." % \
       
  1410                             (format, fixture_name, humanize(fixture_dir))
       
  1411     if count[0] == 0:
       
  1412         if verbosity > 0:
       
  1413             print "No fixtures found."
       
  1414     else:
       
  1415         if verbosity > 0:
       
  1416             print "Installed %d object(s) from %d fixture(s)" % tuple(count)
       
  1417     transaction.commit()
       
  1418     transaction.leave_transaction_management()
       
  1419         
       
  1420 load_data.help_doc = 'Installs the named fixture(s) in the database'
       
  1421 load_data.args = "[--verbosity] fixture, fixture, ..."
       
  1422  
       
  1423 def dump_data(app_labels, format='json', indent=None):
       
  1424     "Output the current contents of the database as a fixture of the given format"
       
  1425     from django.db.models import get_app, get_apps, get_models
       
  1426     from django.core import serializers
       
  1427  
       
  1428     if len(app_labels) == 0:
       
  1429         app_list = get_apps()
       
  1430     else:
       
  1431         app_list = [get_app(app_label) for app_label in app_labels]
       
  1432  
       
  1433     # Check that the serialization format exists; this is a shortcut to
       
  1434     # avoid collating all the objects and _then_ failing.
       
  1435     try:
       
  1436         serializers.get_serializer(format)
       
  1437     except KeyError:
       
  1438         sys.stderr.write(style.ERROR("Unknown serialization format: %s\n" % format))        
       
  1439     
       
  1440     objects = []
       
  1441     for app in app_list:
       
  1442         for model in get_models(app):
       
  1443             objects.extend(model.objects.all())
       
  1444     try:
       
  1445         return serializers.serialize(format, objects, indent=indent)
       
  1446     except Exception, e:
       
  1447         sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e))
       
  1448 dump_data.help_doc = 'Output the contents of the database as a fixture of the given format'
       
  1449 dump_data.args = '[--format]' + APP_ARGS
       
  1450 
       
  1451 # Utilities for command-line script
       
  1452 
       
  1453 DEFAULT_ACTION_MAPPING = {
       
  1454     'adminindex': get_admin_index,
       
  1455     'createcachetable' : createcachetable,
       
  1456     'dbshell': dbshell,
       
  1457     'diffsettings': diffsettings,
       
  1458     'dumpdata': dump_data,
       
  1459     'flush': flush,
       
  1460     'inspectdb': inspectdb,
       
  1461     'loaddata': load_data,
       
  1462     'reset': reset,
       
  1463     'runfcgi': runfcgi,
       
  1464     'runserver': runserver,
       
  1465     'shell': run_shell,
       
  1466     'sql': get_sql_create,
       
  1467     'sqlall': get_sql_all,
       
  1468     'sqlclear': get_sql_delete,
       
  1469     'sqlcustom': get_custom_sql,
       
  1470     'sqlflush': get_sql_flush,
       
  1471     'sqlindexes': get_sql_indexes,
       
  1472     'sqlinitialdata': get_sql_initial_data,
       
  1473     'sqlreset': get_sql_reset,
       
  1474     'sqlsequencereset': get_sql_sequence_reset,
       
  1475     'startapp': startapp,
       
  1476     'startproject': startproject,
       
  1477     'syncdb': syncdb,
       
  1478     'validate': validate,
       
  1479     'test':test,
       
  1480 }
       
  1481 
       
  1482 NO_SQL_TRANSACTION = (
       
  1483     'adminindex',
       
  1484     'createcachetable',
       
  1485     'dbshell',
       
  1486     'diffsettings',
       
  1487     'reset',
       
  1488     'sqlindexes',
       
  1489     'syncdb',
       
  1490 )
       
  1491 
       
  1492 class DjangoOptionParser(OptionParser):
       
  1493     def print_usage_and_exit(self):
       
  1494         self.print_help(sys.stderr)
       
  1495         sys.exit(1)
       
  1496 
       
  1497 def get_usage(action_mapping):
       
  1498     """
       
  1499     Returns a usage string. Doesn't do the options stuff, because optparse
       
  1500     takes care of that.
       
  1501     """
       
  1502     usage = ["%prog action [options]\nactions:"]
       
  1503     available_actions = action_mapping.keys()
       
  1504     available_actions.sort()
       
  1505     for a in available_actions:
       
  1506         func = action_mapping[a]
       
  1507         usage.append("  %s %s" % (a, func.args))
       
  1508         usage.extend(textwrap.wrap(getattr(func, 'help_doc', textwrap.dedent(func.__doc__.strip())), initial_indent='    ', subsequent_indent='    '))
       
  1509         usage.append("")
       
  1510     return '\n'.join(usage[:-1]) # Cut off last list element, an empty space.
       
  1511 
       
  1512 def print_error(msg, cmd):
       
  1513     sys.stderr.write(style.ERROR('Error: %s' % msg) + '\nRun "%s --help" for help.\n' % cmd)
       
  1514     sys.exit(1)
       
  1515 
       
  1516 def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
       
  1517     # Use sys.argv if we've not passed in a custom argv
       
  1518     if argv is None:
       
  1519         argv = sys.argv
       
  1520 
       
  1521     # Parse the command-line arguments. optparse handles the dirty work.
       
  1522     parser = DjangoOptionParser(usage=get_usage(action_mapping), version=get_version())
       
  1523     parser.add_option('--settings',
       
  1524         help='Python path to settings module, e.g. "myproject.settings.main". If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be used.')
       
  1525     parser.add_option('--pythonpath',
       
  1526         help='Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".')
       
  1527     parser.add_option('--plain', action='store_true', dest='plain',
       
  1528         help='Tells Django to use plain Python, not IPython, for "shell" command.')
       
  1529     parser.add_option('--noinput', action='store_false', dest='interactive', default=True,
       
  1530         help='Tells Django to NOT prompt the user for input of any kind.')
       
  1531     parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True,
       
  1532         help='Tells Django to NOT use the auto-reloader when running the development server.')
       
  1533     parser.add_option('--format', default='json', dest='format',
       
  1534         help='Specifies the output serialization format for fixtures')    
       
  1535     parser.add_option('--indent', default=None, dest='indent',
       
  1536         type='int', help='Specifies the indent level to use when pretty-printing output')
       
  1537     parser.add_option('--verbosity', action='store', dest='verbosity', default='1',
       
  1538         type='choice', choices=['0', '1', '2'],
       
  1539         help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'),
       
  1540     parser.add_option('--adminmedia', dest='admin_media_path', default='', help='Specifies the directory from which to serve admin media for runserver.'),
       
  1541 
       
  1542     options, args = parser.parse_args(argv[1:])
       
  1543 
       
  1544     # Take care of options.
       
  1545     if options.settings:
       
  1546         os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
       
  1547     if options.pythonpath:
       
  1548         sys.path.insert(0, options.pythonpath)
       
  1549 
       
  1550     # Run the appropriate action. Unfortunately, optparse can't handle
       
  1551     # positional arguments, so this has to parse/validate them.
       
  1552     try:
       
  1553         action = args[0]
       
  1554     except IndexError:
       
  1555         parser.print_usage_and_exit()
       
  1556     if not action_mapping.has_key(action):
       
  1557         print_error("Your action, %r, was invalid." % action, argv[0])
       
  1558 
       
  1559     # Switch to English, because django-admin.py creates database content
       
  1560     # like permissions, and those shouldn't contain any translations.
       
  1561     # But only do this if we should have a working settings file.
       
  1562     if action not in ('startproject', 'startapp'):
       
  1563         from django.utils import translation
       
  1564         translation.activate('en-us')
       
  1565 
       
  1566     if action == 'shell':
       
  1567         action_mapping[action](options.plain is True)
       
  1568     elif action in ('validate', 'diffsettings', 'dbshell'):
       
  1569         action_mapping[action]()
       
  1570     elif action in ('flush', 'syncdb'):
       
  1571         action_mapping[action](int(options.verbosity), options.interactive)
       
  1572     elif action == 'inspectdb':
       
  1573         try:
       
  1574             for line in action_mapping[action]():
       
  1575                 print line
       
  1576         except NotImplementedError:
       
  1577             sys.stderr.write(style.ERROR("Error: %r isn't supported for the currently selected database backend.\n" % action))
       
  1578             sys.exit(1)
       
  1579     elif action == 'createcachetable':
       
  1580         try:
       
  1581             action_mapping[action](args[1])
       
  1582         except IndexError:
       
  1583             parser.print_usage_and_exit()
       
  1584     elif action in ('test', 'loaddata'):
       
  1585         try:
       
  1586             action_mapping[action](args[1:], int(options.verbosity))
       
  1587         except IndexError:
       
  1588             parser.print_usage_and_exit()
       
  1589     elif action == 'dumpdata':
       
  1590         try:
       
  1591             print action_mapping[action](args[1:], options.format, options.indent)
       
  1592         except IndexError:
       
  1593             parser.print_usage_and_exit()
       
  1594     elif action in ('startapp', 'startproject'):
       
  1595         try:
       
  1596             name = args[1]
       
  1597         except IndexError:
       
  1598             parser.print_usage_and_exit()
       
  1599         action_mapping[action](name, os.getcwd())
       
  1600     elif action == 'runserver':
       
  1601         if len(args) < 2:
       
  1602             addr = ''
       
  1603             port = '8000'
       
  1604         else:
       
  1605             try:
       
  1606                 addr, port = args[1].split(':')
       
  1607             except ValueError:
       
  1608                 addr, port = '', args[1]
       
  1609         action_mapping[action](addr, port, options.use_reloader, options.admin_media_path)
       
  1610     elif action == 'runfcgi':
       
  1611         action_mapping[action](args[1:])
       
  1612     elif action == 'sqlinitialdata':
       
  1613         print action_mapping[action](args[1:])
       
  1614     elif action == 'sqlflush':
       
  1615         print '\n'.join(action_mapping[action]())
       
  1616     else:
       
  1617         from django.db import models
       
  1618         validate(silent_success=True)
       
  1619         try:
       
  1620             mod_list = [models.get_app(app_label) for app_label in args[1:]]
       
  1621         except ImportError, e:
       
  1622             sys.stderr.write(style.ERROR("Error: %s. Are you sure your INSTALLED_APPS setting is correct?\n" % e))
       
  1623             sys.exit(1)
       
  1624         if not mod_list:
       
  1625             parser.print_usage_and_exit()
       
  1626         if action not in NO_SQL_TRANSACTION:
       
  1627             print style.SQL_KEYWORD("BEGIN;")
       
  1628         for mod in mod_list:
       
  1629             if action == 'reset':
       
  1630                 output = action_mapping[action](mod, options.interactive)
       
  1631             else:
       
  1632                 output = action_mapping[action](mod)
       
  1633             if output:
       
  1634                 print '\n'.join(output)
       
  1635         if action not in NO_SQL_TRANSACTION:
       
  1636             print style.SQL_KEYWORD("COMMIT;")
       
  1637 
       
  1638 def setup_environ(settings_mod):
       
  1639     """
       
  1640     Configure the runtime environment. This can also be used by external
       
  1641     scripts wanting to set up a similar environment to manage.py.
       
  1642     """
       
  1643     # Add this project to sys.path so that it's importable in the conventional
       
  1644     # way. For example, if this file (manage.py) lives in a directory
       
  1645     # "myproject", this code would add "/path/to/myproject" to sys.path.
       
  1646     project_directory = os.path.dirname(settings_mod.__file__)
       
  1647     project_name = os.path.basename(project_directory)
       
  1648     sys.path.append(os.path.join(project_directory, '..'))
       
  1649     project_module = __import__(project_name, {}, {}, [''])
       
  1650     sys.path.pop()
       
  1651 
       
  1652     # Set DJANGO_SETTINGS_MODULE appropriately.
       
  1653     os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
       
  1654     return project_directory
       
  1655 
       
  1656 def execute_manager(settings_mod, argv=None):
       
  1657     project_directory = setup_environ(settings_mod)
       
  1658     action_mapping = DEFAULT_ACTION_MAPPING.copy()
       
  1659 
       
  1660     # Remove the "startproject" command from the action_mapping, because that's
       
  1661     # a django-admin.py command, not a manage.py command.
       
  1662     del action_mapping['startproject']
       
  1663 
       
  1664     # Override the startapp handler so that it always uses the
       
  1665     # project_directory, not the current working directory (which is default).
       
  1666     action_mapping['startapp'] = lambda app_name, directory: startapp(app_name, project_directory)
       
  1667     action_mapping['startapp'].__doc__ = startapp.__doc__
       
  1668     action_mapping['startapp'].help_doc = startapp.help_doc
       
  1669     action_mapping['startapp'].args = startapp.args
       
  1670 
       
  1671     # Run the django-admin.py command.
       
  1672     execute_from_command_line(action_mapping, argv)