PageRenderTime 231ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/django/core/management/commands/loaddata.py

https://code.google.com/p/mango-py/
Python | 266 lines | 229 code | 22 blank | 15 comment | 28 complexity | f5d79caf5ce574d3ffab003de7944cb6 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. import sys
  2. import os
  3. import gzip
  4. import zipfile
  5. from optparse import make_option
  6. from django.conf import settings
  7. from django.core import serializers
  8. from django.core.management.base import BaseCommand
  9. from django.core.management.color import no_style
  10. from django.db import connections, router, transaction, DEFAULT_DB_ALIAS
  11. from django.db.models import get_apps
  12. from django.utils.itercompat import product
  13. try:
  14. import bz2
  15. has_bz2 = True
  16. except ImportError:
  17. has_bz2 = False
  18. class LoadFixtureError(Exception):
  19. pass
  20. class Command(BaseCommand):
  21. help = 'Installs the named fixture(s) in the database.'
  22. args = "fixture [fixture ...]"
  23. option_list = BaseCommand.option_list + (
  24. make_option('--database', action='store', dest='database',
  25. default=DEFAULT_DB_ALIAS, help='Nominates a specific database to load '
  26. 'fixtures into. Defaults to the "default" database.'),
  27. )
  28. def handle(self, *fixture_labels, **options):
  29. using = options.get('database', DEFAULT_DB_ALIAS)
  30. #Whether or not we throw exceptions or swallow them
  31. throwexception = options.get('exceptiononerror', False)
  32. connection = connections[using]
  33. self.style = no_style()
  34. verbosity = int(options.get('verbosity', 1))
  35. show_traceback = options.get('traceback', False)
  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. # Keep a count of the installed objects and fixtures
  44. fixture_count = 0
  45. loaded_object_count = 0
  46. fixture_object_count = 0
  47. models = set()
  48. humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
  49. # Get a cursor (even though we don't need one yet). This has
  50. # the side effect of initializing the test database (if
  51. # it isn't already initialized).
  52. cursor = connection.cursor()
  53. # Start transaction management. All fixtures are installed in a
  54. # single transaction to ensure that all references are resolved.
  55. if commit:
  56. transaction.commit_unless_managed(using=using)
  57. transaction.enter_transaction_management(using=using)
  58. transaction.managed(True, using=using)
  59. class SingleZipReader(zipfile.ZipFile):
  60. def __init__(self, *args, **kwargs):
  61. zipfile.ZipFile.__init__(self, *args, **kwargs)
  62. if settings.DEBUG:
  63. assert len(self.namelist()) == 1, "Zip-compressed fixtures must contain only one file."
  64. def read(self):
  65. return zipfile.ZipFile.read(self, self.namelist()[0])
  66. compression_types = {
  67. None: file,
  68. 'gz': gzip.GzipFile,
  69. 'zip': SingleZipReader
  70. }
  71. if has_bz2:
  72. compression_types['bz2'] = bz2.BZ2File
  73. app_module_paths = []
  74. for app in get_apps():
  75. if hasattr(app, '__path__'):
  76. # It's a 'models/' subpackage
  77. for path in app.__path__:
  78. app_module_paths.append(path)
  79. else:
  80. # It's a models.py module
  81. app_module_paths.append(app.__file__)
  82. app_fixtures = [os.path.join(os.path.dirname(path), 'fixtures') for path in app_module_paths]
  83. for fixture_label in fixture_labels:
  84. parts = fixture_label.split('.')
  85. if len(parts) > 1 and parts[-1] in compression_types:
  86. compression_formats = [parts[-1]]
  87. parts = parts[:-1]
  88. else:
  89. compression_formats = compression_types.keys()
  90. if len(parts) == 1:
  91. fixture_name = parts[0]
  92. formats = serializers.get_public_serializer_formats()
  93. else:
  94. fixture_name, format = '.'.join(parts[:-1]), parts[-1]
  95. if format in serializers.get_public_serializer_formats():
  96. formats = [format]
  97. else:
  98. formats = []
  99. if formats:
  100. if verbosity >= 2:
  101. self.stdout.write("Loading '%s' fixtures...\n" % fixture_name)
  102. else:
  103. errstr = "Problem installing fixture '%s': %s is not a known serialization format.\n" % (fixture_name, format)
  104. self.stderr.write(self.style.ERROR(errstr))
  105. if commit:
  106. transaction.rollback(using=using)
  107. transaction.leave_transaction_management(using=using)
  108. if throwexception:
  109. raise LoadFixtureError(errstr)
  110. else:
  111. return
  112. if os.path.isabs(fixture_name):
  113. fixture_dirs = [fixture_name]
  114. else:
  115. fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + ['']
  116. for fixture_dir in fixture_dirs:
  117. if verbosity >= 2:
  118. self.stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir))
  119. label_found = False
  120. for combo in product([using, None], formats, compression_formats):
  121. database, format, compression_format = combo
  122. file_name = '.'.join(
  123. p for p in [
  124. fixture_name, database, format, compression_format
  125. ]
  126. if p
  127. )
  128. if verbosity >= 3:
  129. self.stdout.write("Trying %s for %s fixture '%s'...\n" % \
  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. errstr = "Multiple fixtures named '%s' in %s. Aborting.\n" % (fixture_name, humanize(fixture_dir))
  137. fixture.close()
  138. self.stderr.write(self.style.ERROR(errstr))
  139. if commit:
  140. transaction.rollback(using=using)
  141. transaction.leave_transaction_management(using=using)
  142. if throwexception:
  143. raise LoadFixtureError(errstr)
  144. else:
  145. return
  146. else:
  147. fixture_count += 1
  148. objects_in_fixture = 0
  149. loaded_objects_in_fixture = 0
  150. if verbosity >= 2:
  151. self.stdout.write("Installing %s fixture '%s' from %s.\n" % \
  152. (format, fixture_name, humanize(fixture_dir)))
  153. try:
  154. objects = serializers.deserialize(format, fixture, using=using)
  155. for obj in objects:
  156. objects_in_fixture += 1
  157. if router.allow_syncdb(using, obj.object.__class__):
  158. loaded_objects_in_fixture += 1
  159. models.add(obj.object.__class__)
  160. obj.save(using=using)
  161. loaded_object_count += loaded_objects_in_fixture
  162. fixture_object_count += objects_in_fixture
  163. label_found = True
  164. except (SystemExit, KeyboardInterrupt):
  165. raise
  166. except Exception, e:
  167. import traceback
  168. fixture.close()
  169. if commit:
  170. transaction.rollback(using=using)
  171. transaction.leave_transaction_management(using=using)
  172. if show_traceback:
  173. traceback.print_exc()
  174. else:
  175. errstr = "Problem installing fixture '%s': %s\n" % \
  176. (full_path, ''.join(traceback.format_exception(sys.exc_type,
  177. sys.exc_value, sys.exc_traceback)))
  178. self.stderr.write(self.style.ERROR(errstr))
  179. if throwexception:
  180. raise LoadFixtureError()
  181. else:
  182. return
  183. fixture.close()
  184. # If the fixture we loaded contains 0 objects, assume that an
  185. # error was encountered during fixture loading.
  186. if objects_in_fixture == 0:
  187. errstr = "No fixture data found for '%s'. (File format may be invalid.)\n" % (fixture_name)
  188. self.stderr.write(self.style.ERROR(errstr))
  189. if commit:
  190. transaction.rollback(using=using)
  191. transaction.leave_transaction_management(using=using)
  192. if throwexception:
  193. raise LoadFixtureError(errstr)
  194. else:
  195. return
  196. except LoadFixtureError:
  197. raise
  198. except Exception, e:
  199. errstr = "%s" % e
  200. if verbosity >= 2:
  201. errstr = "No %s fixture '%s' in %s.\n" % (format, fixture_name, humanize(fixture_dir))
  202. self.stdout.write(errstr)
  203. # If we found even one object in a fixture, we need to reset the
  204. # database sequences.
  205. if loaded_object_count > 0:
  206. sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
  207. if sequence_sql:
  208. if verbosity >= 2:
  209. self.stdout.write("Resetting sequences\n")
  210. for line in sequence_sql:
  211. cursor.execute(line)
  212. if commit:
  213. transaction.commit(using=using)
  214. transaction.leave_transaction_management(using=using)
  215. if fixture_object_count == 0:
  216. if verbosity >= 1:
  217. self.stdout.write("No fixtures found.\n")
  218. else:
  219. if verbosity >= 1:
  220. if fixture_object_count == loaded_object_count:
  221. self.stdout.write("Installed %d object(s) from %d fixture(s)\n" % (
  222. loaded_object_count, fixture_count))
  223. else:
  224. self.stdout.write("Installed %d object(s) (of %d) from %d fixture(s)\n" % (
  225. loaded_object_count, fixture_object_count, fixture_count))
  226. # Close the DB connection. This is required as a workaround for an
  227. # edge case in MySQL: if the same connection is used to
  228. # create tables, load data, and query, the query can return
  229. # incorrect results. See Django #7572, MySQL #37735.
  230. if commit:
  231. connection.close()