web/lib/django/core/management/commands/loaddata.py
changeset 0 0d40e90630ef
child 29 cc9b7e14412b
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 import sys
       
     2 import os
       
     3 import gzip
       
     4 import zipfile
       
     5 from optparse import make_option
       
     6 
       
     7 from django.core.management.base import BaseCommand
       
     8 from django.core.management.color import no_style
       
     9 
       
    10 try:
       
    11     set
       
    12 except NameError:
       
    13     from sets import Set as set   # Python 2.3 fallback
       
    14 
       
    15 try:
       
    16     import bz2
       
    17     has_bz2 = True
       
    18 except ImportError:
       
    19     has_bz2 = False
       
    20 
       
    21 class Command(BaseCommand):
       
    22     help = 'Installs the named fixture(s) in the database.'
       
    23     args = "fixture [fixture ...]"
       
    24 
       
    25     def handle(self, *fixture_labels, **options):
       
    26         from django.db.models import get_apps
       
    27         from django.core import serializers
       
    28         from django.db import connection, transaction
       
    29         from django.conf import settings
       
    30 
       
    31         self.style = no_style()
       
    32 
       
    33         verbosity = int(options.get('verbosity', 1))
       
    34         show_traceback = options.get('traceback', False)
       
    35 
       
    36         # commit is a stealth option - it isn't really useful as
       
    37         # a command line option, but it can be useful when invoking
       
    38         # loaddata from within another script.
       
    39         # If commit=True, loaddata will use its own transaction;
       
    40         # if commit=False, the data load SQL will become part of
       
    41         # the transaction in place when loaddata was invoked.
       
    42         commit = options.get('commit', True)
       
    43 
       
    44         # Keep a count of the installed objects and fixtures
       
    45         fixture_count = 0
       
    46         object_count = 0
       
    47         models = set()
       
    48 
       
    49         humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
       
    50 
       
    51         # Get a cursor (even though we don't need one yet). This has
       
    52         # the side effect of initializing the test database (if
       
    53         # it isn't already initialized).
       
    54         cursor = connection.cursor()
       
    55 
       
    56         # Start transaction management. All fixtures are installed in a
       
    57         # single transaction to ensure that all references are resolved.
       
    58         if commit:
       
    59             transaction.commit_unless_managed()
       
    60             transaction.enter_transaction_management()
       
    61             transaction.managed(True)
       
    62 
       
    63         class SingleZipReader(zipfile.ZipFile):
       
    64             def __init__(self, *args, **kwargs):
       
    65                 zipfile.ZipFile.__init__(self, *args, **kwargs)
       
    66                 if settings.DEBUG:
       
    67                     assert len(self.namelist()) == 1, "Zip-compressed fixtures must contain only one file."
       
    68             def read(self):
       
    69                 return zipfile.ZipFile.read(self, self.namelist()[0])
       
    70 
       
    71         compression_types = {
       
    72             None:   file,
       
    73             'gz':   gzip.GzipFile,
       
    74             'zip':  SingleZipReader
       
    75         }
       
    76         if has_bz2:
       
    77             compression_types['bz2'] = bz2.BZ2File
       
    78 
       
    79         app_fixtures = [os.path.join(os.path.dirname(app.__file__), 'fixtures') for app in get_apps()]
       
    80         for fixture_label in fixture_labels:
       
    81             parts = fixture_label.split('.')
       
    82 
       
    83             if len(parts) > 1 and parts[-1] in compression_types:
       
    84                 compression_formats = [parts[-1]]
       
    85                 parts = parts[:-1]
       
    86             else:
       
    87                 compression_formats = compression_types.keys()
       
    88 
       
    89             if len(parts) == 1:
       
    90                 fixture_name = parts[0]
       
    91                 formats = serializers.get_public_serializer_formats()
       
    92             else:
       
    93                 fixture_name, format = '.'.join(parts[:-1]), parts[-1]
       
    94                 if format in serializers.get_public_serializer_formats():
       
    95                     formats = [format]
       
    96                 else:
       
    97                     formats = []
       
    98 
       
    99             if formats:
       
   100                 if verbosity > 1:
       
   101                     print "Loading '%s' fixtures..." % fixture_name
       
   102             else:
       
   103                 sys.stderr.write(
       
   104                     self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format." %
       
   105                         (fixture_name, format)))
       
   106                 transaction.rollback()
       
   107                 transaction.leave_transaction_management()
       
   108                 return
       
   109 
       
   110             if os.path.isabs(fixture_name):
       
   111                 fixture_dirs = [fixture_name]
       
   112             else:
       
   113                 fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + ['']
       
   114 
       
   115             for fixture_dir in fixture_dirs:
       
   116                 if verbosity > 1:
       
   117                     print "Checking %s for fixtures..." % humanize(fixture_dir)
       
   118 
       
   119                 label_found = False
       
   120                 for format in formats:
       
   121                     for compression_format in compression_formats:
       
   122                         if compression_format: 
       
   123                             file_name = '.'.join([fixture_name, format, 
       
   124                                                   compression_format])
       
   125                         else: 
       
   126                             file_name = '.'.join([fixture_name, format])
       
   127                     
       
   128                         if verbosity > 1:
       
   129                             print "Trying %s for %s fixture '%s'..." % \
       
   130                                 (humanize(fixture_dir), file_name, fixture_name)
       
   131                         full_path = os.path.join(fixture_dir, file_name)
       
   132                         open_method = compression_types[compression_format]                                
       
   133                         try: 
       
   134                             fixture = open_method(full_path, 'r')
       
   135                             if label_found:
       
   136                                 fixture.close()
       
   137                                 print self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting." %
       
   138                                     (fixture_name, humanize(fixture_dir)))
       
   139                                 transaction.rollback()
       
   140                                 transaction.leave_transaction_management()
       
   141                                 return
       
   142                             else:
       
   143                                 fixture_count += 1
       
   144                                 objects_in_fixture = 0
       
   145                                 if verbosity > 0:
       
   146                                     print "Installing %s fixture '%s' from %s." % \
       
   147                                         (format, fixture_name, humanize(fixture_dir))
       
   148                                 try:
       
   149                                     objects = serializers.deserialize(format, fixture)
       
   150                                     for obj in objects:
       
   151                                         objects_in_fixture += 1
       
   152                                         models.add(obj.object.__class__)
       
   153                                         obj.save()
       
   154                                     object_count += objects_in_fixture
       
   155                                     label_found = True
       
   156                                 except (SystemExit, KeyboardInterrupt):
       
   157                                     raise
       
   158                                 except Exception:
       
   159                                     import traceback
       
   160                                     fixture.close()
       
   161                                     transaction.rollback()
       
   162                                     transaction.leave_transaction_management()
       
   163                                     if show_traceback:
       
   164                                         traceback.print_exc()
       
   165                                     else:
       
   166                                         sys.stderr.write(
       
   167                                             self.style.ERROR("Problem installing fixture '%s': %s\n" %
       
   168                                                  (full_path, ''.join(traceback.format_exception(sys.exc_type, 
       
   169                                                      sys.exc_value, sys.exc_traceback))))) 
       
   170                                     return
       
   171                                 fixture.close()
       
   172 
       
   173                                 # If the fixture we loaded contains 0 objects, assume that an
       
   174                                 # error was encountered during fixture loading.
       
   175                                 if objects_in_fixture == 0:
       
   176                                     sys.stderr.write(
       
   177                                         self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)" %
       
   178                                             (fixture_name)))
       
   179                                     transaction.rollback()
       
   180                                     transaction.leave_transaction_management()
       
   181                                     return
       
   182 
       
   183                         except Exception, e:
       
   184                             if verbosity > 1:
       
   185                                 print "No %s fixture '%s' in %s." % \
       
   186                                     (format, fixture_name, humanize(fixture_dir))
       
   187 
       
   188         # If we found even one object in a fixture, we need to reset the
       
   189         # database sequences.
       
   190         if object_count > 0:
       
   191             sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
       
   192             if sequence_sql:
       
   193                 if verbosity > 1:
       
   194                     print "Resetting sequences"
       
   195                 for line in sequence_sql:
       
   196                     cursor.execute(line)
       
   197 
       
   198         if commit:
       
   199             transaction.commit()
       
   200             transaction.leave_transaction_management()
       
   201 
       
   202         if object_count == 0:
       
   203             if verbosity > 1:
       
   204                 print "No fixtures found."
       
   205         else:
       
   206             if verbosity > 0:
       
   207                 print "Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count)
       
   208 
       
   209         # Close the DB connection. This is required as a workaround for an
       
   210         # edge case in MySQL: if the same connection is used to
       
   211         # create tables, load data, and query, the query can return
       
   212         # incorrect results. See Django #7572, MySQL #37735.
       
   213         if commit:
       
   214             connection.close()