Django

Code

Changeset 5898

Show
Ignore:
Timestamp:
08/16/07 01:06:55 (2 years ago)
Author:
adrian
Message:

Major refactoring of django.core.management -- it's now a package rather than a 1730-line single module. All django-admin/manage.py commands are now stored in separate modules. This is backwards-incompatible for people who used django.core.management functions directly

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/core/management/__init__.py

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

    r5858 r5898  
    22from urlparse import urlparse 
    33from django.db import transaction 
    4 from django.core import management, mail 
     4from django.core import mail 
     5from django.core.management import call_command 
    56from django.db.models import get_apps 
    67from django.test import _doctest as doctest 
     
    4344             
    4445        """ 
    45         management.flush(verbosity=0, interactive=False) 
     46        call_command('flush', verbosity=0, interactive=False) 
    4647        if hasattr(self, 'fixtures'): 
    47             management.load_data(self.fixtures, verbosity=0) 
     48            # We have to use this slightly awkward syntax due to the fact 
     49            # that we're using *args and **kwargs together. 
     50            call_command('loaddata', *self.fixtures, **{'verbosity': 0}) 
    4851        mail.outbox = [] 
    4952 
  • django/trunk/django/test/utils.py

    r5766 r5898  
    22from django.conf import settings 
    33from django.db import connection, backend, get_creation_module 
    4 from django.core import management, mail 
    5 from django.core import management, mail 
     4from django.core import mail 
     5from django.core.management import call_command 
    66from django.dispatch import dispatcher 
    77from django.test import signals 
     
    1919    dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context) 
    2020    return self.nodelist.render(context) 
    21      
     21 
    2222class TestSMTPConnection(object): 
    2323    """A substitute SMTP connection for use during test sessions. 
    2424    The test connection stores email messages in a dummy outbox, 
    2525    rather than sending them out on the wire. 
    26      
     26 
    2727    """ 
    2828    def __init__(*args, **kwargs): 
     
    4040def setup_test_environment(): 
    4141    """Perform any global pre-test setup. This involves: 
    42          
     42 
    4343        - Installing the instrumented test renderer 
    4444        - Diverting the email sending functions to a test buffer 
    45          
     45 
    4646    """ 
    4747    Template.original_render = Template.render 
    4848    Template.render = instrumented_test_render 
    49      
     49 
    5050    mail.original_SMTPConnection = mail.SMTPConnection 
    5151    mail.SMTPConnection = TestSMTPConnection 
    5252 
    5353    mail.outbox = [] 
    54      
     54 
    5555def teardown_test_environment(): 
    5656    """Perform any global post-test teardown. This involves: 
     
    5858        - Restoring the original test renderer 
    5959        - Restoring the email sending functions 
    60          
     60 
    6161    """ 
    6262    Template.render = Template.original_render 
    6363    del Template.original_render 
    64      
     64 
    6565    mail.SMTPConnection = mail.original_SMTPConnection 
    6666    del mail.original_SMTPConnection 
    67      
     67 
    6868    del mail.outbox 
    69      
     69 
    7070def _set_autocommit(connection): 
    7171    "Make sure a connection is in autocommit mode." 
     
    9595        creation_module.create_test_db(settings, connection, backend, verbosity, autoclobber) 
    9696        return 
    97      
     97 
    9898    if verbosity >= 1: 
    9999        print "Creating test database..." 
     
    113113        else: 
    114114            TEST_DATABASE_NAME = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 
    115          
     115 
    116116        # Create the test database and connect to it. We need to autocommit 
    117         # if the database supports it because PostgreSQL doesn't allow  
     117        # if the database supports it because PostgreSQL doesn't allow 
    118118        # CREATE/DROP DATABASE statements within transactions. 
    119119        cursor = connection.cursor() 
     
    121121        try: 
    122122            cursor.execute("CREATE DATABASE %s %s" % (backend.quote_name(TEST_DATABASE_NAME), suffix)) 
    123         except Exception, e:             
     123        except Exception, e: 
    124124            sys.stderr.write("Got an error creating the test database: %s\n" % e) 
    125125            if not autoclobber: 
     
    128128                try: 
    129129                    if verbosity >= 1: 
    130                         print "Destroying old test database..."                 
     130                        print "Destroying old test database..." 
    131131                    cursor.execute("DROP DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME)) 
    132132                    if verbosity >= 1: 
     
    139139                print "Tests cancelled." 
    140140                sys.exit(1) 
    141                 
     141 
    142142    connection.close() 
    143143    settings.DATABASE_NAME = TEST_DATABASE_NAME 
    144144 
    145     management.syncdb(verbosity, interactive=False) 
     145    call_command('syncdb', verbosity=verbosity, interactive=False) 
    146146 
    147147    if settings.CACHE_BACKEND.startswith('db://'): 
    148148        cache_name = settings.CACHE_BACKEND[len('db://'):] 
    149         management.createcachetable(cache_name) 
     149        call_command('createcachetable', cache_name) 
    150150 
    151151    # Get a cursor (even though we don't need one yet). This has 
     
    159159        creation_module.destroy_test_db(settings, connection, backend, old_database_name, verbosity) 
    160160        return 
    161      
     161 
    162162    # Unless we're using SQLite, remove the test database to clean up after 
    163163    # ourselves. Connect to the previous database (not the test database) 
  • django/trunk/tests/modeltests/fixtures/models.py

    r5876 r5898  
    2727# Reset the database representation of this app. 
    2828# This will return the database to a clean initial state. 
    29 >>> management.flush(verbosity=0, interactive=False) 
     29>>> management.call_command('flush', verbosity=0, interactive=False) 
    3030 
    3131# Syncdb introduces 1 initial data object from initial_data.json. 
     
    3434 
    3535# Load fixture 1. Single JSON file, with two objects. 
    36 >>> management.load_data(['fixture1.json'], verbosity=0) 
     36>>> management.call_command('loaddata', 'fixture1.json', verbosity=0) 
    3737>>> Article.objects.all() 
    3838[<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] 
    3939 
    4040# Load fixture 2. JSON file imported by default. Overwrites some existing objects 
    41 >>> management.load_data(['fixture2.json'], verbosity=0) 
     41>>> management.call_command('loaddata', 'fixture2.json', verbosity=0) 
    4242>>> Article.objects.all() 
    4343[<Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] 
    4444 
    4545# Load fixture 3, XML format. 
    46 >>> management.load_data(['fixture3.xml'], verbosity=0) 
     46>>> management.call_command('loaddata', 'fixture3.xml', verbosity=0) 
    4747>>> Article.objects.all() 
    4848[<Article: XML identified as leading cause of cancer>, <Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker on TV is great!>, <Article: Python program becomes self aware>] 
    4949 
    5050# Load a fixture that doesn't exist 
    51 >>> management.load_data(['unknown.json'], verbosity=0) 
     51>>> management.call_command('loaddata', 'unknown.json', verbosity=0) 
    5252 
    5353# object list is unaffected 
     
    5656 
    5757# Reset the database representation of this app. This will delete all data. 
    58 >>> management.flush(verbosity=0, interactive=False) 
     58>>> management.call_command('flush', verbosity=0, interactive=False) 
    5959>>> Article.objects.all() 
    6060[<Article: Python program becomes self aware>] 
    6161 
    6262# Load fixture 1 again, using format discovery 
    63 >>> management.load_data(['fixture1'], verbosity=0) 
     63>>> management.call_command('loaddata', 'fixture1', verbosity=0) 
    6464>>> Article.objects.all() 
    6565[<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] 
     
    6767# Try to load fixture 2 using format discovery; this will fail 
    6868# because there are two fixture2's in the fixtures directory 
    69 >>> management.load_data(['fixture2'], verbosity=0) # doctest: +ELLIPSIS 
     69>>> management.call_command('loaddata', 'fixture2', verbosity=0) # doctest: +ELLIPSIS 
    7070Multiple fixtures named 'fixture2' in '...fixtures'. Aborting. 
    7171 
     
    7474 
    7575# Dump the current contents of the database as a JSON fixture 
    76 >>> print management.dump_data(['fixtures'], format='json') 
     76>>> print management.call_command('dumpdata', 'fixtures', format='json') 
    7777[{"pk": "3", "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "2", "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": "1", "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}] 
    7878"""} 
  • django/trunk/tests/regressiontests/fixtures_regress/models.py

    r5876 r5898  
    2727 
    2828# Load a fixture that uses PK=1 
    29 >>> management.load_data(['sequence'], verbosity=0) 
     29>>> management.call_command('loaddata', 'sequence', verbosity=0) 
    3030         
    3131# Create a new animal. Without a sequence reset, this new object 
     
    4040 
    4141# Load a pretty-printed XML fixture with Nulls. 
    42 >>> management.load_data(['pretty.xml'], verbosity=0) 
     42>>> management.call_command('loaddata', 'pretty.xml', verbosity=0) 
    4343>>> Stuff.objects.all() 
    4444[<Stuff: None is owned by None>] 
  • django/trunk/tests/regressiontests/serializers_regress/tests.py

    r5876 r5898  
    274274def serializerTest(format, self): 
    275275    # Clear the database first 
    276     management.flush(verbosity=0, interactive=False) 
     276    management.call_command('flush', verbosity=0, interactive=False) 
    277277 
    278278    # Create all the objects defined in the test data 
     
    292292 
    293293    # Flush the database and recreate from the serialized data 
    294     management.flush(verbosity=0, interactive=False) 
     294    management.call_command('flush', verbosity=0, interactive=False) 
    295295    transaction.enter_transaction_management() 
    296296    transaction.managed(True) 
     
    307307def fieldsTest(format, self): 
    308308    # Clear the database first 
    309     management.flush(verbosity=0, interactive=False) 
     309    management.call_command('flush', verbosity=0, interactive=False) 
    310310 
    311311    obj = ComplexModel(field1='first',field2='second',field3='third') 
     
    323323def streamTest(format, self): 
    324324    # Clear the database first 
    325     management.flush(verbosity=0, interactive=False) 
     325    management.call_command('flush', verbosity=0, interactive=False) 
    326326 
    327327    obj = ComplexModel(field1='first',field2='second',field3='third') 
  • django/trunk/tests/runtests.py

    r5893 r5898  
    5252 
    5353    def runTest(self): 
    54         from django.core import management 
     54        from django.core.management.validation import get_validation_errors 
    5555        from django.db.models.loading import load_app 
    5656        from cStringIO import StringIO 
     
    6262 
    6363        s = StringIO() 
    64         count = management.get_validation_errors(s, module) 
     64        count = get_validation_errors(s, module) 
    6565        s.seek(0) 
    6666        error_log = s.read()