Changeset 4659
- Timestamp:
- 03/01/07 07:11:08 (1 year ago)
- Files:
-
- django/trunk/django/conf/global_settings.py (modified) (1 diff)
- django/trunk/django/core/management.py (modified) (18 diffs)
- django/trunk/django/core/serializers/base.py (modified) (1 diff)
- django/trunk/django/core/serializers/__init__.py (modified) (1 diff)
- django/trunk/django/db/backends/ado_mssql/base.py (modified) (1 diff)
- django/trunk/django/db/backends/dummy/base.py (modified) (1 diff)
- django/trunk/django/db/backends/mysql/base.py (modified) (1 diff)
- django/trunk/django/db/backends/oracle/base.py (modified) (1 diff)
- django/trunk/django/db/backends/postgresql/base.py (modified) (3 diffs)
- django/trunk/django/db/backends/postgresql_psycopg2/base.py (modified) (3 diffs)
- django/trunk/django/db/backends/sqlite3/base.py (modified) (1 diff)
- django/trunk/django/test/__init__.py (modified) (1 diff)
- django/trunk/django/test/testcases.py (modified) (2 diffs)
- django/trunk/docs/django-admin.txt (modified) (6 diffs)
- django/trunk/docs/settings.txt (modified) (2 diffs)
- django/trunk/docs/testing.txt (modified) (2 diffs)
- django/trunk/tests/modeltests/fixtures (added)
- django/trunk/tests/modeltests/fixtures/fixtures (added)
- django/trunk/tests/modeltests/fixtures/fixtures/fixture1.json (added)
- django/trunk/tests/modeltests/fixtures/fixtures/fixture2.json (added)
- django/trunk/tests/modeltests/fixtures/fixtures/fixture2.xml (added)
- django/trunk/tests/modeltests/fixtures/fixtures/fixture3.xml (added)
- django/trunk/tests/modeltests/fixtures/fixtures/initial_data.json (added)
- django/trunk/tests/modeltests/fixtures/__init__.py (added)
- django/trunk/tests/modeltests/fixtures/models.py (added)
- django/trunk/tests/modeltests/test_client/fixtures (added)
- django/trunk/tests/modeltests/test_client/fixtures/testdata.json (added)
- django/trunk/tests/modeltests/test_client/management.py (deleted)
- django/trunk/tests/modeltests/test_client/models.py (modified) (1 diff)
- django/trunk/tests/urls.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/conf/global_settings.py
r4631 r4659 320 320 # If None, a name of 'test_' + DATABASE_NAME will be assumed 321 321 TEST_DATABASE_NAME = None 322 323 ############ 324 # FIXTURES # 325 ############ 326 327 # The list of directories to search for fixtures 328 FIXTURE_DIRS = () django/trunk/django/core/management.py
r4610 r4659 68 68 cursor = connection.cursor() 69 69 return get_introspection_module().get_table_list(cursor) 70 71 def _get_sequence_list(): 72 "Returns a list of information about all DB sequences for all models in all apps" 73 from django.db import models 74 75 apps = models.get_apps() 76 sequence_list = [] 77 78 for app in apps: 79 for model in models.get_models(app): 80 for f in model._meta.fields: 81 if isinstance(f, models.AutoField): 82 sequence_list.append({'table':model._meta.db_table,'column':f.column,}) 83 break # Only one AutoField is allowed per model, so don't bother continuing. 84 85 for f in model._meta.many_to_many: 86 sequence_list.append({'table':f.m2m_db_table(),'column':None,}) 87 88 return sequence_list 70 89 71 90 # If the foreign key points to an AutoField, a PositiveIntegerField or a … … 335 354 get_sql_reset.args = APP_ARGS 336 355 337 def get_sql_initial_data_for_model(model): 356 def get_sql_flush(): 357 "Returns a list of the SQL statements used to flush the database" 358 from django.db import backend 359 statements = backend.get_sql_flush(style, _get_table_list(), _get_sequence_list()) 360 return statements 361 get_sql_flush.help_doc = "Returns a list of the SQL statements required to return all tables in the database to the state they were in just after they were installed." 362 get_sql_flush.args = '' 363 364 def get_custom_sql_for_model(model): 338 365 from django.db import models 339 366 from django.conf import settings … … 362 389 return output 363 390 364 def get_ sql_initial_data(app):365 "Returns a list of the initial INSERTSQL statements for the given app."391 def get_custom_sql(app): 392 "Returns a list of the custom table modifying SQL statements for the given app." 366 393 from django.db.models import get_models 367 394 output = [] … … 371 398 372 399 for model in app_models: 373 output.extend(get_ sql_initial_data_for_model(model))400 output.extend(get_custom_sql_for_model(model)) 374 401 375 402 return output 376 get_sql_initial_data.help_doc = "Prints the initial INSERT SQL statements for the given app name(s)." 377 get_sql_initial_data.args = APP_ARGS 403 get_custom_sql.help_doc = "Prints the custom table modifying SQL statements for the given app name(s)." 404 get_custom_sql.args = APP_ARGS 405 406 def get_sql_initial_data(apps): 407 "Returns a list of the initial INSERT SQL statements for the given app." 408 return style.ERROR("This action has been renamed. Try './manage.py sqlcustom %s'." % ' '.join(apps and apps or ['app1', 'app2'])) 409 get_sql_initial_data.help_doc = "RENAMED: see 'sqlcustom'" 410 get_sql_initial_data.args = '' 378 411 379 412 def get_sql_sequence_reset(app): … … 433 466 def get_sql_all(app): 434 467 "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module." 435 return get_sql_create(app) + get_ sql_initial_data(app) + get_sql_indexes(app)468 return get_sql_create(app) + get_custom_sql(app) + get_sql_indexes(app) 436 469 get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)." 437 470 get_sql_all.args = APP_ARGS 471 472 def _emit_post_sync_signal(created_models, verbosity, interactive): 473 from django.db import models 474 from django.dispatch import dispatcher 475 # Emit the post_sync signal for every application. 476 for app in models.get_apps(): 477 app_name = app.__name__.split('.')[-2] 478 if verbosity >= 2: 479 print "Running post-sync handlers for application", app_name 480 dispatcher.send(signal=models.signals.post_syncdb, sender=app, 481 app=app, created_models=created_models, 482 verbosity=verbosity, interactive=interactive) 438 483 439 484 def syncdb(verbosity=1, interactive=True): 440 485 "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." 441 486 from django.db import connection, transaction, models, get_creation_module 442 from django.db.models import signals443 487 from django.conf import settings 444 from django.dispatch import dispatcher445 488 446 489 disable_termcolors() … … 504 547 # Send the post_syncdb signal, so individual apps can do whatever they need 505 548 # to do at this point. 549 _emit_post_sync_signal(created_models, verbosity, interactive) 550 551 # Install custom SQL for the app (but only if this 552 # is a model we've just created) 506 553 for app in models.get_apps(): 507 app_name = app.__name__.split('.')[-2]508 if verbosity >= 2:509 print "Running post-sync handlers for application", app_name510 dispatcher.send(signal=signals.post_syncdb, sender=app,511 app=app, created_models=created_models,512 verbosity=verbosity, interactive=interactive)513 514 # Install initial data for the app (but only if this is a model we've515 # just created)516 554 for model in models.get_models(app): 517 555 if model in created_models: 518 initial_sql = get_sql_initial_data_for_model(model)519 if initial_sql:556 custom_sql = get_custom_sql_for_model(model) 557 if custom_sql: 520 558 if verbosity >= 1: 521 print "Installing initial datafor %s.%s model" % (app_name, model._meta.object_name)559 print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name) 522 560 try: 523 for sql in initial_sql:561 for sql in custom_sql: 524 562 cursor.execute(sql) 525 563 except Exception, e: 526 sys.stderr.write("Failed to install initial SQL datafor %s.%s model: %s" % \564 sys.stderr.write("Failed to install custom SQL for %s.%s model: %s" % \ 527 565 (app_name, model._meta.object_name, e)) 528 566 transaction.rollback_unless_managed() … … 549 587 transaction.commit_unless_managed() 550 588 551 syncdb.args = '' 589 # Install the 'initialdata' fixture, using format discovery 590 load_data(['initial_data'], verbosity=verbosity) 591 syncdb.help_doc = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." 592 syncdb.args = '[--verbosity] [--interactive]' 552 593 553 594 def get_admin_index(app): … … 602 643 diffsettings.args = "" 603 644 604 def install(app):605 "Executes the equivalent of 'get_sql_all' in the current database."606 from django.db import connection, transaction607 608 app_name = app.__name__.split('.')[-2]609 610 disable_termcolors()611 612 # First, try validating the models.613 _check_for_validation_errors(app)614 615 sql_list = get_sql_all(app)616 617 try:618 cursor = connection.cursor()619 for sql in sql_list:620 cursor.execute(sql)621 except Exception, e:622 sys.stderr.write(style.ERROR("""Error: %s couldn't be installed. Possible reasons:623 * The database isn't running or isn't configured correctly.624 * At least one of the database tables already exists.625 * The SQL was invalid.626 Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this command wasn't able to run.627 The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')628 transaction.rollback_unless_managed()629 sys.exit(1)630 transaction.commit_unless_managed()631 install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database."632 install.args = APP_ARGS633 634 645 def reset(app, interactive=True): 635 646 "Executes the equivalent of 'get_sql_reset' in the current database." … … 673 684 print "Reset cancelled." 674 685 reset.help_doc = "Executes ``sqlreset`` for the given app(s) in the current database." 675 reset.args = APP_ARGS 686 reset.args = '[--interactive]' + APP_ARGS 687 688 def flush(verbosity=1, interactive=True): 689 "Returns all tables in the database to the same state they were in immediately after syncdb." 690 from django.conf import settings 691 from django.db import connection, transaction, models 692 from django.dispatch import dispatcher 693 694 disable_termcolors() 695 696 # First, try validating the models. 697 _check_for_validation_errors() 698 699 # Import the 'management' module within each installed app, to register 700 # dispatcher events. 701 for app_name in settings.INSTALLED_APPS: 702 try: 703 __import__(app_name + '.management', {}, {}, ['']) 704 except ImportError: 705 pass 706 707 sql_list = get_sql_flush() 708 709 if interactive: 710 confirm = raw_input(""" 711 You have requested a flush of the database. 712 This will IRREVERSIBLY DESTROY all data currently in the database, 713 and return each table to the state it was in after syncdb. 714 Are you sure you want to do this? 715 716 Type 'yes' to continue, or 'no' to cancel: """) 717 else: 718 confirm = 'yes' 719 720 if confirm == 'yes': 721 try: 722 cursor = connection.cursor() 723 for sql in sql_list: 724 cursor.execute(sql) 725 except Exception, e: 726 sys.stderr.write(style.ERROR("""Error: Database %s couldn't be flushed. Possible reasons: 727 * The database isn't running or isn't configured correctly. 728 * At least one of the expected database tables doesn't exist. 729 * The SQL was invalid. 730 Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run. 731 The full error: """ % settings.DATABASE_NAME + style.ERROR_OUTPUT(str(e)) + '\n')) 732 transaction.rollback_unless_managed() 733 sys.exit(1) 734 transaction.commit_unless_managed() 735 736 # Emit the post sync signal. This allows individual 737 # applications to respond as if the database had been 738 # sync'd from scratch. 739 _emit_post_sync_signal(models.get_models(), verbosity, interactive) 740 741 # Reinstall the initial_data fixture 742 load_data(['initial_data'], verbosity=verbosity) 743 744 else: 745 print "Flush cancelled." 746 flush.help_doc = "Executes ``sqlflush`` on the current database." 747 flush.args = '[--verbosity] [--interactive]' 676 748 677 749 def _start_helper(app_or_project, name, directory, other_name=''): … … 756 828 yield "# Feel free to rename the models, but don't rename db_table values or field names." 757 829 yield "#" 758 yield "# Also note: You'll have to insert the output of 'django-admin.py sql initialdata[appname]'"830 yield "# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]'" 759 831 yield "# into your database." 760 832 yield '' … … 1252 1324 test.args = '[--verbosity] ' + APP_ARGS 1253 1325 1326 def load_data(fixture_labels, verbosity=1): 1327 "Installs the provided fixture file(s) as data in the database." 1328 from django.db.models import get_apps 1329 from django.core import serializers 1330 from django.db import connection, transaction 1331 from django.conf import settings 1332 import sys 1333 1334 # Keep a count of the installed objects and fixtures 1335 count = [0,0] 1336 1337 humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path' 1338 1339 # Get a cursor (even though we don't need one yet). This has 1340 # the side effect of initializing the test database (if 1341 # it isn't already initialized). 1342 cursor = connection.cursor() 1343 1344 # Start transaction management. All fixtures are installed in a 1345 # single transaction to ensure that all references are resolved. 1346 transaction.commit_unless_managed() 1347 transaction.enter_transaction_management() 1348 transaction.managed(True) 1349 1350 app_fixtures = [os.path.join(os.path.dirname(app.__file__),'fixtures') for app in get_apps()] 1351 for fixture_label in fixture_labels: 1352 if verbosity > 0: 1353 print "Loading '%s' fixtures..." % fixture_label 1354 for fixture_dir in app_fixtures + list(settings.FIXTURE_DIRS) + ['']: 1355 if verbosity > 1: 1356 print "Checking %s for fixtures..." % humanize(fixture_dir) 1357 try: 1358 fixture_name, format = fixture_label.rsplit('.', 1) 1359 formats = [format] 1360 except ValueError: 1361 fixture_name = fixture_label 1362 formats = serializers.get_serializer_formats() 1363 1364 label_found = False 1365 for format in formats: 1366 serializer = serializers.get_serializer(format) 1367 if verbosity > 1: 1368 print "Trying %s for %s fixture '%s'..." % \ 1369 (humanize(fixture_dir), format, fixture_name) 1370 try: 1371 full_path = os.path.join(fixture_dir, '.'.join([fixture_name, format])) 1372 fixture = open(full_path, 'r') 1373 if label_found: 1374 fixture.close() 1375 print style.ERROR("Multiple fixtures named '%s' in %s. Aborting." % 1376 (fixture_name, humanize(fixture_dir))) 1377 transaction.rollback() 1378 transaction.leave_transaction_management() 1379 return 1380 else: 1381 count[1] += 1 1382 if verbosity > 0: 1383 print "Installing %s fixture '%s' from %s." % \ 1384 (format, fixture_name, humanize(fixture_dir)) 1385 try: 1386 objects = serializers.deserialize(format, fixture) 1387 for obj in objects: 1388 count[0] += 1 1389 obj.save() 1390 label_found = True 1391 except Exception, e: 1392 fixture.close() 1393 sys.stderr.write( 1394 style.ERROR("Problem installing fixture '%s': %s\n" % 1395 (full_path, str(e)))) 1396 transaction.rollback() 1397 transaction.leave_transaction_management() 1398 return 1399 fixture.close() 1400 except: 1401 if verbosity > 1: 1402 print "No %s fixture '%s' in %s." % \ 1403 (format, fixture_name, humanize(fixture_dir)) 1404 if count[0] == 0: 1405 if verbosity > 0: 1406 print "No fixtures found." 1407 else: 1408 if verbosity > 0: 1409 print "Installed %d object(s) from %d fixture(s)" % tuple(count) 1410 transaction.commit() 1411 transaction.leave_transaction_management() 1412 1413 load_data.help_doc = 'Installs the named fixture(s) in the database' 1414 load_data.args = "[--verbosity] fixture, fixture, ..." 1415 1416 def dump_data(app_labels, format='json'): 1417 "Output the current contents of the database as a fixture of the given format" 1418 from django.db.models import get_app, get_apps, get_models 1419 from django.core import serializers 1420 1421 if len(app_labels) == 0: 1422 app_list = get_apps() 1423 else: 1424 app_list = [get_app(app_label) for app_label in app_labels] 1425 1426 # Check that the serialization format exists; this is a shortcut to 1427 # avoid collating all the objects and _then_ failing. 1428 try: 1429 serializers.get_serializer(format) 1430 except KeyError: 1431 sys.stderr.write(style.ERROR("Unknown serialization format: %s\n" % format)) 1432 1433 objects = [] 1434 for app in app_list: 1435 for model in get_models(app): 1436 objects.extend(model.objects.all()) 1437 try: 1438 print serializers.serialize(format, objects) 1439 except Exception, e: 1440 sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e)) 1441 dump_data.help_doc = 'Output the contents of the database as a fixture of the given format' 1442 dump_data.args = '[--format]' + APP_ARGS 1443 1254 1444 # Utilities for command-line script 1255 1445 … … 1259 1449 'dbshell': dbshell, 1260 1450 'diffsettings': diffsettings, 1451 'dumpdata': dump_data, 1452 'flush': flush, 1261 1453 'inspectdb': inspectdb, 1262 ' install': install,1454 'loaddata': load_data, 1263 1455 'reset': reset, 1264 1456 'runfcgi': runfcgi, … … 1268 1460 'sqlall': get_sql_all, 1269 1461 'sqlclear': get_sql_delete, 1462 'sqlcustom': get_custom_sql, 1463 'sqlflush': get_sql_flush, 1270 1464 'sqlindexes': get_sql_indexes, 1271 1465 'sqlinitialdata': get_sql_initial_data, … … 1284 1478 'dbshell', 1285 1479 'diffsettings', 1286 'install',1287 1480 'reset', 1288 1481 'sqlindexes', … … 1331 1524 parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True, 1332 1525 help='Tells Django to NOT use the auto-reloader when running the development server.') 1526 parser.add_option('--format', default='json', dest='format', 1527 help='Specifies the output serialization format for fixtures') 1333 1528 parser.add_option('--verbosity', action='store', dest='verbosity', default='1', 1334 1529 type='choice', choices=['0', '1', '2'], … … 1364 1559 elif action in ('validate', 'diffsettings', 'dbshell'): 1365 1560 action_mapping[action]() 1366 elif action == 'syncdb':1561 elif action in ('flush', 'syncdb'): 1367 1562 action_mapping[action](int(options.verbosity), options.interactive) 1368 1563 elif action == 'inspectdb': … … 1378 1573 except IndexError: 1379 1574 parser.print_usage_and_exit() 1380 elif action == 'test':1575 elif action in ('test', 'loaddata'): 1381 1576 try: 1382 1577 action_mapping[action](args[1:], int(options.verbosity)) 1578 except IndexError: 1579 parser.print_usage_and_exit() 1580 elif action == 'dumpdata': 1581 try: 1582 action_mapping[action](args[1:], options.format) 1383 1583 except IndexError: 1384 1584 parser.print_usage_and_exit() … … 1401 1601 elif action == 'runfcgi': 1402 1602 action_mapping[action](args[1:]) 1603 elif action == 'sqlinitialdata': 1604 print action_mapping[action](args[1:]) 1605 elif action == 'sqlflush': 1606 print '\n'.join(action_mapping[action]()) 1403 1607 else: 1404 1608 from django.db import models django/trunk/django/core/serializers/base.py
r4265 r4659 142 142 class DeserializedObject(object): 143 143 """ 144 A deserial zed model.144 A deserialized model. 145 145 146 146 Basically a container for holding the pre-saved deserialized data along django/trunk/django/core/serializers/__init__.py
r4265 r4659 41 41 _load_serializers() 42 42 return _serializers[format].Serializer 43 44 def get_serializer_formats(): 45 if not _serializers: 46 _load_serializers() 47 return _serializers.keys() 43 48 44 49 def get_deserializer(format): django/trunk/django/db/backends/ado_mssql/base.py
r4610 r4659 138 138 return "DEFAULT" 139 139 140 def get_sql_flush(sql_styler, full_table_list): 141 """Return a list of SQL statements required to remove all data from 142 all tables in the database (without actually removing the tables 143 themselves) and put the database in an empty 'initial' state 144 """ 145 # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements 146 # TODO - SQL not actually tested against ADO MSSQL yet! 147 # TODO - autoincrement indices reset required? See other get_sql_flush() implementations 148 sql_list = ['%s %s;' % \ 149 (sql_styler.SQL_KEYWORD('TRUNCATE'), 150 sql_styler.SQL_FIELD(quote_name(table)) 151 ) for table in full_table_list] 152 140 153 OPERATOR_MAPPING = { 141 154 'exact': '= %s', django/trunk/django/db/backends/dummy/base.py
r4610 r4659 40 40 get_fulltext_search_sql = complain 41 41 get_drop_foreignkey_sql = complain 42 get_sql_flush = complain 43 42 44 OPERATOR_MAPPING = {} django/trunk/django/db/backends/mysql/base.py
r4610 r4659 187 187 return "DEFAULT" 188 188 189 def get_sql_flush(style, tables, sequences): 190 """Return a list of SQL statements required to remove all data from 191 all tables in the database (without actually removing the tables 192 themselves) and put the database in an empty 'initial' state 193 194 """ 195 # NB: The generated SQL below is specific to MySQL 196 # 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements 197 # to clear all tables of all data 198 if tables: 199 sql = ['SET FOREIGN_KEY_CHECKS = 0;'] + \ 200 ['%s %s;' % \ 201 (style.SQL_KEYWORD('TRUNCATE'), 202 style.SQL_FIELD(quote_name(table)) 203 ) for table in tables] + \ 204 ['SET FOREIGN_KEY_CHECKS = 1;'] 205 206 # 'ALTER TABLE table AUTO_INCREMENT = 1;'... style SQL statements 207 # to reset sequence indices 208 sql.extend(["%s %s %s %s %s;" % \ 209 (style.SQL_KEYWORD('ALTER'), 210 style.SQL_KEYWORD('TABLE'), 211 style.SQL_TABLE(quote_name(sequence['table'])), 212 style.SQL_KEYWORD('AUTO_INCREMENT'), 213 style.SQL_FIELD('= 1'), 214 ) for sequence in sequences]) 215 return sql 216 else: 217 return [] 218 189 219 OPERATOR_MAPPING = { 190 220 'exact': '= %s', django/trunk/django/db/backends/oracle/base.py
r4610 r4659 121 121 return "DEFAULT" 122 122 123 def get_sql_flush(style, tables, sequences): 124 """Return a list of SQL statements required to remove all data from 125 all tables in the database (without actually removing the tables 126 themselves) and put the database in an empty 'initial' state 127 """ 128 # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements 129 # TODO - SQL not actually tested against Oracle yet! 130 # TODO - autoincrement indices reset required? See other get_sql_flush() implementations 131 sql = ['%s %s;' % \ 132 (style.SQL_KEYWORD('TRUNCATE'), 133 style.SQL_FIELD(quote_name(table)) 134 ) for table in tables] 135 136 123 137 OPERATOR_MAPPING = { 124 138 'exact': '= %s', django/trunk/django/db/backends/postgresql/base.py
r4610 r4659 52 52 else: 53 53 return getattr(self.cursor, attr) 54 55 postgres_version = None 54 56 55 57 class DatabaseWrapper(local): … … 82 84 cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE]) 83 85 cursor = UnicodeCursorWrapper(cursor, settings.DEFAULT_CHARSET) 86 global postgres_version 87 if not postgres_version: 88 cursor.execute("SELECT version()") 89 postgres_version = [int(val) for val in cursor.dictfetchone()['version'].split()[1].split('.')] 84 90 if settings.DEBUG: 85 91 return util.CursorDebugWrapper(cursor, self) … … 152 158 return "DEFAULT" 153 159 160 def get_sql_flush(style, tables, sequences): 161 """Return a list of SQL statements required to remove all data from 162 all tables in the database (without actually removing the tables 163 themselves) and put the database in an empty 'initial' state 164 165 """ 166 if tables: 167 if postgres_version[0] >= 8 and postgres_version[1] >= 1: 168 # Postgres 8.1+ can do 'TRUNCATE x, y, z...;'. In fact, it *has to* in order to be able to 169 # truncate tables referenced by a foreign key in any other table. The result is a 170 # single SQL TRUNCATE statement. 171 sql = ['%s %s;' % \ 172 (style.SQL_KEYWORD('TRUNCATE'), 173 style.SQL_FIELD(', '.join(quote_name(table) for table in tables)) 174 )] 175 else: 176 # Older versions of Postgres can't do TRUNCATE in a single call, so they must use 177 # a simple delete. 178 sql = ['%s %s %s;' % \ 179 (style.SQL_KEYWORD('DELETE'), 180 style.SQL_KEYWORD('FROM'), 181 style.SQL_FIELD(quote_name(table)) 182 ) for table in tables] 183 184 # 'ALTER SEQUENCE sequence_name RESTART WITH 1;'... style SQL statements 185 # to reset sequence indices 186 for sequence_info in sequences: 187 table_name = sequence_info['table'] 188 column_name = sequence_info['column'] 189 if column_name and len(column_name)>0: 190 # sequence name in this case will be <table>_<column>_seq 191 sql.append("%s %s %s %s %s %s;" % \ 192 (style.SQL_KEYWORD('ALTER'), 193 style.SQL_KEYWORD('SEQUENCE'), 194 style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)), 195 style.SQL_KEYWORD('RESTART'), 196 style.SQL_KEYWORD('WITH'), 197 style.SQL_FIELD('1') 198 ) 199 ) 200 else: 201 # sequence name in this case will be <table>_id_seq 202 sql.append("%s %s %s %s %s %s;" % \ 203 (style.SQL_KEYWORD('ALTER'), 204 style.SQL_KEYWORD('SEQUENCE'), 205 style.SQL_FIELD('%s_id_seq' % table_name), 206 style.SQL_KEYWORD('RESTART'), 207 style.SQL_KEYWORD('WITH'), 208 style.SQL_FIELD('1') 209 ) 210 ) 211 return sql 212 else: 213 return [] 214 215 154 216 # Register these custom typecasts, because Django expects dates/times to be 155 217 # in Python's native (standard-library) datetime/time format, whereas psycopg django/trunk/django/db/backends/postgresql_psycopg2/base.py
r4610 r4659 20 20 # Import copy of _thread_local.py from Python 2.4 21 21 from django.utils._threading_local import local 22 23 postgres_version = None 22 24 23 25 class DatabaseWrapper(local): … … 50 52 if set_tz: 51 53 cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE]) 54 global postgres_version 55 if not postgres_version: 56 cursor.execute("SELECT version()") 57 postgres_version = [int(val) for val in cursor.dictfetchone()['version'].split()[1].split('.')] 52 58 if settings.DEBUG: 53 59 return util.CursorDebugWrapper(cursor, self) … … 112 118 return "DEFAULT" 113 119 120 def get_sql_flush(style, tables, sequences): 121 """Return a list of SQL statements required to remove all data from 122 all tables in the database (without actually removing the tables 123 themselves) and put the database in an empty 'initial' state 124 """ 125 if tables: 126 if postgres_version[0] >= 8 and postgres_version[1] >= 1: 127 # Postgres 8.1+ can do 'TRUNCATE x, y, z...;'. In fact, it *has to* in order to be able to 128 # truncate tables referenced by a foreign key in any other table. The result is a 129 # single SQL TRUNCATE statement 130 sql = ['%s %s;' % \ 131 (style.SQL_KEYWORD('TRUNCATE'), 132 style.SQL_FIELD(', '.join(quote_name(table) for table in tables)) 133 )] 134 else: 135 sql = ['%s %s %s;' % \ 136 (style.SQL_KEYWORD('DELETE'), 137 style.SQL_KEYWORD('FROM'), 138 style.SQL_FIELD(quote_name(table)) 139 ) for table in tables] 140 141 # 'ALTER SEQUENCE sequence_name RESTART WITH 1;'... style SQL statements 142 # to reset sequence indices 143 for sequence in sequences: 144 table_name = sequence['table'] 145 column_name = sequence['column'] 146 if column_name and len(column_name) > 0: 147 # sequence name in this case will be <table>_<column>_seq 148 sql.append("%s %s %s %s %s %s;" % \ 149 (style.SQL_KEYWORD('ALTER'), 150 style.SQL_KEYWORD('SEQUENCE'), 151 style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)), 152 style.SQL_KEYWORD('RESTART'), 153 style.SQL_KEYWORD('WITH'), 154 style.SQL_FIELD('1') 155 ) 156 ) 157 else: 158 # sequence name in this case will be <table>_id_seq 159 sql.append("%s %s %s %s %s %s;" % \ 160 (style.SQL_KEYWORD('ALTER'), 161 style.SQL_KEYWORD('SEQUENCE'), 162 style.SQL_FIELD('%s_id_seq' % table_name), 163 style.SQL_KEYWORD('RESTART'), 164 style.SQL_KEYWORD('WITH'), 165 style.SQL_FIELD('1') 166 ) 167 ) 168 return sql 169 else: 170 return [] 171 114 172 OPERATOR_MAPPING = { 115 173 'exact': '= %s', django/trunk/django/db/backends/sqlite3/base.py
r4610 r4659 152 152 return "NULL" 153 153 154 def get_sql_flush(style, tables, sequences): 155 """Return a list of SQL statements required to remove all data from 156 all tables in the database (without actually removing the tables 157 themselves) and put the database in an empty 'initial' state 158 159 """ 160 # NB: The generated SQL below is specific to SQLite 161 # Note: The DELETE FROM... SQL generated below works for SQLite databases 162 # because constraints don't exist 163 sql = ['%s %s %s;' % \ 164 (style.SQL_KEYWORD('DELETE'), 165 style.SQL_KEYWORD('FROM'), 166 style.SQL_FIELD(quote_name(table)) 167 ) for table in tables] 168 # Note: No requirement for reset of auto-incremented indices (cf. other 169 # get_sql_flush() implementations). Just return SQL at this point 170 return sql 171 154 172 def _sqlite_date_trunc(lookup_type, dt): 155 173 try: django/trunk/django/test/__init__.py
r4265 r4659 1 """ 2 Django Unit Test and Doctest framework. 3 """ 4 5 from django.test.client import Client 6 from django.test.testcases import TestCase django/trunk/django/test/testcases.py
r4265 r4659 1 1 import re, doctest, unittest 2 2 from django.db import transaction 3 from django.core import management 4 from django.db.models import get_apps 3 5 4 6 normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s) … … 29 31 transaction.rollback_unless_managed() 30 32 33 class TestCase(unittest.TestCase): 34 def install_fixtures(self): 35 """If the Test Case class has a 'fixtures' member, clear the database and 36 install the named fixtures at the start of each test. 37 38 """ 39 management.flush(verbosity=0, interactive=False) 40 if hasattr(self, 'fixtures'): 41 management.load_data(self.fixtures, verbosity=0) 42 43 def run(self, result=None): 44 """Wrapper around default run method so that user-defined Test Cases 45 automatically call install_fixtures without having to include a call to 46 super(). 47 48 """ 49 self.install_fixtures() 50 super(TestCase, self).run(result) django/trunk/docs/django-admin.txt
r4651 r4659 97 97 Note that Django's default settings live in ``django/conf/global_settings.py``, 98 98 if you're ever curious to see the full list of defaults. 99 100 dumpdata [appname appname ...] 101 ------------------------------ 102 103 **New in Django development version** 104 105 Output to standard output all data in the database associated with the named 106 application(s). 107 108 By default, the database will be dumped in JSON format. If you want the output 109 to be in another format, use the ``--format`` option (e.g., ``format=xml``). 110 You may specify any Django serialization backend (inclu
