Ticket #11838: ticket11838-2.diff
File ticket11838-2.diff, 23.7 KB (added by , 15 years ago) |
---|
-
django/core/management/commands/loaddata.py
6 6 7 7 from django.core.management.base import BaseCommand 8 8 from django.core.management.color import no_style 9 from django.core import serializers 10 from django.db import transaction 9 11 10 12 try: 11 13 set … … 24 26 25 27 def handle(self, *fixture_labels, **options): 26 28 from django.db.models import get_apps 27 from django.core import serializers 28 from django.db import connection, transaction 29 from django.db import connection 29 30 from django.conf import settings 30 31 31 32 self.style = no_style() 32 33 33 verbosity = int(options.get('verbosity', 1))34 s how_traceback = options.get('traceback', False)34 self.verbosity = int(options.get('verbosity', 1)) 35 self.show_traceback = options.get('traceback', False) 35 36 36 37 # commit is a stealth option - it isn't really useful as 37 38 # a command line option, but it can be useful when invoking … … 43 44 44 45 # Keep a count of the installed objects and fixtures 45 46 fixture_count = 0 46 object_count = 047 models = set()47 self.object_count = 0 48 self.models = set() 48 49 49 humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'50 self.humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path' 50 51 51 52 # Get a cursor (even though we don't need one yet). This has 52 53 # the side effect of initializing the test database (if … … 88 89 89 90 if len(parts) == 1: 90 91 fixture_name = parts[0] 92 fixture_format = None 91 93 formats = serializers.get_public_serializer_formats() 92 94 else: 93 95 fixture_name, format = '.'.join(parts[:-1]), parts[-1] 94 96 if format in serializers.get_public_serializer_formats(): 97 fixture_format = format 95 98 formats = [format] 96 99 else: 97 100 formats = [] 98 101 99 102 if formats: 100 if verbosity > 1:103 if self.verbosity > 1: 101 104 print "Loading '%s' fixtures..." % fixture_name 102 105 else: 103 106 sys.stderr.write( … … 113 116 fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + [''] 114 117 115 118 for fixture_dir in fixture_dirs: 116 if verbosity > 1:117 print "Checking %s for fixtures..." % humanize(fixture_dir)119 if self.verbosity > 1: 120 print "Checking %s for fixtures..." % self.humanize(fixture_dir) 118 121 119 122 label_found = False 120 123 for format in formats: … … 125 128 else: 126 129 file_name = '.'.join([fixture_name, format]) 127 130 128 if verbosity > 1:131 if self.verbosity > 1: 129 132 print "Trying %s for %s fixture '%s'..." % \ 130 ( humanize(fixture_dir), file_name, fixture_name)133 (self.humanize(fixture_dir), file_name, fixture_name) 131 134 full_path = os.path.join(fixture_dir, file_name) 132 135 open_method = compression_types[compression_format] 133 136 try: … … 135 138 if label_found: 136 139 fixture.close() 137 140 print self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting." % 138 (fixture_name, humanize(fixture_dir)))141 (fixture_name, self.humanize(fixture_dir))) 139 142 transaction.rollback() 140 143 transaction.leave_transaction_management() 141 144 return 142 145 else: 143 146 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))))) 147 label_found, error = self.install_fixture(format, fixture, fixture_name, fixture_dir, full_path) 148 if error: 170 149 return 171 fixture.close()172 173 # If the fixture we loaded contains 0 objects, assume that an174 # 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 return182 183 150 except Exception, e: 184 if verbosity > 1:151 if self.verbosity > 1: 185 152 print "No %s fixture '%s' in %s." % \ 186 (format, fixture_name, humanize(fixture_dir))153 (format, fixture_name, self.humanize(fixture_dir)) 187 154 155 # Check for a group of fixtures with the requested name 156 if not fixture_format: 157 group_dir = os.path.join(fixture_dir, fixture_name) 158 if os.path.isdir(group_dir): 159 if label_found: 160 print self.style.ERROR("A fixture named '%s' and a fixture group named '%s' were both found in %s. Aborting." % 161 (fixture_name, fixture_name, self.humanize(fixture_dir))) 162 transaction.rollback() 163 transaction.leave_transaction_management() 164 return 165 else: 166 labels_found = [] 167 if self.verbosity > 1: 168 print "Checking %s for a group of fixtures." % \ 169 self.humanize(group_dir) 170 for file_name in os.listdir(group_dir): 171 parts = file_name.split('.') 172 173 if len(parts) > 2 and parts[-1] in compression_types: 174 compression_format = parts[-1] 175 parts = parts[:-1] 176 else: 177 compression_format = None 178 179 if len(parts) == 2: 180 group_fixture_name, format = '.'.join(parts[:-1]), parts[-1] 181 182 if format in serializers.get_public_serializer_formats(): 183 full_path = os.path.join(group_dir, file_name) 184 if self.verbosity > 1: 185 print "Trying %s for %s fixture '%s'..." % \ 186 (self.humanize(group_dir), file_name, 187 fixture_name) 188 open_method = compression_types[compression_format] 189 try: 190 fixture = open_method(full_path, 'r') 191 if group_fixture_name in labels_found: 192 fixture.close() 193 print self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting." % 194 (group_fixture_name, self.humanize(group_dir))) 195 transaction.rollback() 196 transaction.leave_transaction_management() 197 return 198 fixture_count += 1 199 label_found, error = self.install_fixture(format, fixture, group_fixture_name, group_dir, full_path) 200 if error: 201 return 202 if label_found: 203 labels_found += [label_found] 204 except Exception, e: 205 if self.verbosity > 1: 206 print "No %s fixture '%s' in %s." % \ 207 (format, group_fixture_name, self.humanize(group_dir)) 208 188 209 # If we found even one object in a fixture, we need to reset the 189 210 # database sequences. 190 if object_count > 0:191 sequence_sql = connection.ops.sequence_reset_sql(self.style, models)211 if self.object_count > 0: 212 sequence_sql = connection.ops.sequence_reset_sql(self.style, self.models) 192 213 if sequence_sql: 193 if verbosity > 1:214 if self.verbosity > 1: 194 215 print "Resetting sequences" 195 216 for line in sequence_sql: 196 217 cursor.execute(line) … … 199 220 transaction.commit() 200 221 transaction.leave_transaction_management() 201 222 202 if object_count == 0:203 if verbosity > 1:223 if self.object_count == 0: 224 if self.verbosity > 1: 204 225 print "No fixtures found." 205 226 else: 206 if verbosity > 0:207 print "Installed %d object(s) from %d fixture(s)" % ( object_count, fixture_count)227 if self.verbosity > 0: 228 print "Installed %d object(s) from %d fixture(s)" % (self.object_count, fixture_count) 208 229 209 230 # Close the DB connection. This is required as a workaround for an 210 231 # edge case in MySQL: if the same connection is used to … … 212 233 # incorrect results. See Django #7572, MySQL #37735. 213 234 if commit: 214 235 connection.close() 236 237 def install_fixture(self, format, fixture, fixture_name, fixture_dir, full_path): 238 """ 239 Installs the requested fixture. 240 241 Returns: 242 label_found - The name of the label found. 243 error - Whether there was an error while installing the fixture 244 """ 245 error = False 246 label_found = False 247 objects_in_fixture = 0 248 if self.verbosity > 0: 249 print "Installing %s fixture '%s' from %s." % \ 250 (format, fixture_name, self.humanize(fixture_dir)) 251 try: 252 objects = serializers.deserialize(format, fixture) 253 for obj in objects: 254 objects_in_fixture += 1 255 self.models.add(obj.object.__class__) 256 obj.save() 257 self.object_count += objects_in_fixture 258 label_found = fixture_name 259 except (SystemExit, KeyboardInterrupt): 260 raise 261 except Exception: 262 import traceback 263 fixture.close() 264 transaction.rollback() 265 transaction.leave_transaction_management() 266 if self.show_traceback: 267 traceback.print_exc() 268 else: 269 sys.stderr.write( 270 self.style.ERROR("Problem installing fixture '%s': %s\n" % 271 (full_path, ''.join(traceback.format_exception(sys.exc_type, 272 sys.exc_value, sys.exc_traceback))))) 273 error = True 274 return label_found, error 275 fixture.close() 276 277 # If the fixture we loaded contains 0 objects, assume that an 278 # error was encountered during fixture loading. 279 if objects_in_fixture == 0: 280 sys.stderr.write( 281 self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)" % 282 (fixture_name))) 283 transaction.rollback() 284 transaction.leave_transaction_management() 285 error = True 286 return label_found, error 287 288 return label_found, error -
tests/modeltests/fixtures/fixtures/group3/fixture1.json
1 [ 2 { 3 "pk": "8", 4 "model": "fixtures.article", 5 "fields": { 6 "headline": "Researchers use Python to produce the Ultimate Question of Life, the Universe, and Everything", 7 "pub_date": "2009-12-06 11:00:00" 8 } 9 } 10 ] 11 No newline at end of file -
tests/modeltests/fixtures/fixtures/group3/fixture2.json
1 [ 2 { 3 "pk": 8, 4 "model": "fixtures.category", 5 "fields": { 6 "description": "Latest catastrophic disasters", 7 "title": "Catastrophic Disasters" 8 } 9 } 10 ] 11 No newline at end of file -
tests/modeltests/fixtures/fixtures/group4/fixture2.json
1 [ 2 { 3 "pk": 9, 4 "model": "fixtures.category", 5 "fields": { 6 "description": "Amusing hypochondriac anecdotes", 7 "title": "Hypochondriac Anecdotes" 8 } 9 } 10 ] 11 No newline at end of file -
tests/modeltests/fixtures/fixtures/group1.json
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: tests/modeltests/fixtures/fixtures/group4/fixture1.json.gz ___________________________________________________________________ Added: svn:mime-type + application/octet-stream
1 [ 2 { 3 "pk": "6", 4 "model": "fixtures.article", 5 "fields": { 6 "headline": "Guido awarded Nobel Prize", 7 "pub_date": "2009-12-06 11:00:00" 8 } 9 } 10 ] 11 No newline at end of file -
tests/modeltests/fixtures/fixtures/group1/fixture1.json
1 [ 2 { 3 "pk": "6", 4 "model": "fixtures.article", 5 "fields": { 6 "headline": "This fixture should never be installed", 7 "pub_date": "2009-12-06 11:00:00" 8 } 9 } 10 ] 11 No newline at end of file -
tests/modeltests/fixtures/fixtures/group2/fixture1.json
1 [ 2 { 3 "pk": "7", 4 "model": "fixtures.article", 5 "fields": { 6 "headline": "This fixture will cause the transaction to be rolled back", 7 "pub_date": "2009-12-06 11:00:00" 8 } 9 } 10 ] 11 No newline at end of file -
tests/modeltests/fixtures/fixtures/group2/fixture1.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="7" model="fixtures.article"> 4 <field type="CharField" name="headline">This fixture will load, but then be rolled back</field> 5 <field type="DateTimeField" name="pub_date">2009-12-06 11:00:00</field> 6 </object> 7 </django-objects> 8 No newline at end of file -
tests/modeltests/fixtures/models.py
159 159 >>> management.call_command('loaddata', 'fixture5', verbosity=0) # doctest: +ELLIPSIS 160 160 Multiple fixtures named 'fixture5' in '...fixtures'. Aborting. 161 161 162 # Try to load fixture group 1 using format discovery; this will fail because 163 # there is a fixture and a group both named 'group1' in the fixtures 164 # directory. 165 >>> management.call_command('loaddata', 'group1', verbosity=0) # doctest: +ELLIPSIS 166 A fixture named 'group1' and a fixture group named 'group1' were both found in '...fixtures'. Aborting. 167 168 # Load the individual fixture group1 with the full filename; this will succeed 169 # because the format was explicitly specified. The group of fixtures 170 # will be ignored. 171 >>> management.call_command('loaddata', 'group1.json', verbosity=0) 172 >>> Article.objects.all() 173 [<Article: Guido awarded Nobel Prize>, <Article: Python program becomes self aware>] 174 175 >>> management.call_command('flush', verbosity=0, interactive=False) 176 177 # Try to load group 2; this will fail because there are two fixtures in the 178 # group named 'fixture1'. 179 >>> management.call_command('loaddata', 'group2', verbosity=0) # doctest: +ELLIPSIS 180 Multiple fixtures named 'fixture1' in '.../fixtures/group2'. Aborting. 181 182 # Load group 3, which will successfully load 2 fixtures. 183 >>> management.call_command('loaddata', 'group3', verbosity=0) 184 >>> Article.objects.all() 185 [<Article: Researchers use Python to produce the Ultimate Question of Life, the Universe, and Everything>, <Article: Python program becomes self aware>] 186 >>> Category.objects.all() 187 [<Category: Catastrophic Disasters>] 188 189 >>> management.call_command('flush', verbosity=0, interactive=False) 190 191 # Load group 4, which includes 1 gzipped fixture and 1 plain text fixture. 192 >>> management.call_command('loaddata', 'group4', verbosity=0) 193 >>> Article.objects.all() 194 [<Article: Pinky successfully ponders what Brain is pondering, lab in uproar>, <Article: Python program becomes self aware>] 195 >>> Category.objects.all() 196 [<Category: Hypochondriac Anecdotes>] 162 197 """ 163 198 164 199 from django.test import TestCase -
AUTHORS
250 250 Bruce Kroeze <http://coderseye.com/> 251 251 krzysiek.pawlik@silvermedia.pl 252 252 Joseph Kocherhans 253 Brandon Konkle (bkonkle) <http://brandonkonkle.com/> 253 254 konrad@gwu.edu 254 255 knox <christobzr@gmail.com> 255 256 David Krauth -
docs/howto/initial-data.txt
82 82 but be careful: remember that the data will be refreshed *every time* you run 83 83 :djadmin:`syncdb`. So don't use ``initial_data`` for data you'll want to edit. 84 84 85 .. versionadded:: 1.2 86 87 This also works with fixture groups. If you create a subdirectory called 88 ``initial_data`` within a fixtures directory, then all fixture files in 89 that subdirectory will be loaded each time you run :djadmin:`syncdb`. 90 85 91 .. seealso:: 86 92 87 93 Fixtures are also used by the :ref:`testing framework -
docs/ref/django-admin.txt
351 351 352 352 The ``dumpdata`` command can be used to generate input for ``loaddata``. 353 353 354 Fixture groups 355 ~~~~~~~~~~~~~~ 356 357 .. versionadded:: 1.2 358 359 Fixtures can also be grouped together into subdirectories under the 360 ``fixtures`` directory. The subdirectory can be referred to as a fixture, and 361 :djadmin:`loaddata` will try to load each file in the subdirectory as a fixture 362 file. 363 364 For example, say you have an app called ``blog`` with two models, ``Entry`` and 365 ``Category``. If you want to separate your entries into multiple fixture 366 files based on their category, you could create a subdirectory underneath your 367 ``blog`` app's ``fixtures`` directory called ``entries``. Within 368 ``blog/fixtures/entries/`` you could create two fixture files, ``django.json`` 369 and ``python.json``. 370 371 In this case, you can refer to the fixture group ``entries`` to install both 372 fixtures at the same time. :djadmin:`loaddata` will first try to find individual 373 fixtures matching the name requested, and if it doesn't find any it will then 374 try to look for a fixture group with that name. The command:: 375 376 django-admin.py loaddata entries 377 378 would first search for an individual fixture named ``entries``, and when it 379 didn't find one it would look for a subdirectory with that name under each 380 fixture directory. When it found one, it would attempt to install each file 381 within the subdirectory as a fixture. Both ``django.json`` and ``python.json`` 382 would be loaded. 383 384 If you wanted to install only one of the fixtures in the group, you could refer 385 to it specifically with the command:: 386 387 django-admin.py loaddata entries/django.json 388 389 and it would load just the ``django.json`` file. 390 354 391 Compressed fixtures 355 392 ~~~~~~~~~~~~~~~~~~~ 356 393