Ticket #2333: fixtures-2.diff
File fixtures-2.diff, 43.4 KB (added by , 18 years ago) |
---|
-
django/test/testcases.py
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) 5 7 … … 19 21 def __init__(self, *args, **kwargs): 20 22 doctest.DocTestRunner.__init__(self, *args, **kwargs) 21 23 self.optionflags = doctest.ELLIPSIS 24 management.flush(verbosity=0, interactive=False) 22 25 23 26 def report_unexpected_exception(self, out, test, example, exc_info): 24 27 doctest.DocTestRunner.report_unexpected_exception(self,out,test,example,exc_info) … … 28 31 from django.db import transaction 29 32 transaction.rollback_unless_managed() 30 33 34 class TestCase(unittest.TestCase): 35 def install_fixtures(self): 36 """If the Test Case class has a 'fixtures' member, clear the database and 37 install the named fixtures at the start of each test. 38 39 """ 40 management.flush(verbosity=0, interactive=False) 41 if hasattr(self, 'fixtures'): 42 management.load_data(self.fixtures, verbosity=0) 43 44 def run(self, result=None): 45 """Wrapper around default run method so that user-defined Test Cases 46 automatically call install_fixtures without having to include a call to 47 super(). 48 49 """ 50 self.install_fixtures() 51 super(TestCase, self).run(result) -
django/test/__init__.py
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/db/backends/ado_mssql/base.py
134 134 def get_pk_default_value(): 135 135 return "DEFAULT" 136 136 137 def get_sql_flush(sql_styler, full_table_list): 138 """Return a list of SQL statements required to remove all data from 139 all tables in the database (without actually removing the tables 140 themselves) and put the database in an empty 'initial' state 141 """ 142 # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements 143 # TODO - SQL not actually tested against ADO MSSQL yet! 144 # TODO - autoincrement indices reset required? See other get_sql_flush() implementations 145 sql_list = ['%s %s;' % \ 146 (sql_styler.SQL_KEYWORD('TRUNCATE'), 147 sql_styler.SQL_FIELD(quote_name(table)) 148 ) for table in full_table_list] 149 137 150 OPERATOR_MAPPING = { 138 151 'exact': '= %s', 139 152 'iexact': 'LIKE %s', -
django/db/backends/postgresql/base.py
145 145 def get_pk_default_value(): 146 146 return "DEFAULT" 147 147 148 def get_sql_flush(style, tables, sequences): 149 """Return a list of SQL statements required to remove all data from 150 all tables in the database (without actually removing the tables 151 themselves) and put the database in an empty 'initial' state 152 153 """ 154 # Postgres can do 'TRUNCATE x, y, z...;'. In fact, it *has to* in order to be able to 155 # truncate tables referenced by a foreign key in any other table. The result is a 156 # single SQL TRUNCATE statement. 157 if tables: 158 sql = ['%s %s;' % \ 159 (style.SQL_KEYWORD('TRUNCATE'), 160 style.SQL_FIELD(', '.join(quote_name(table) for table in tables)) 161 )] 162 163 # 'ALTER SEQUENCE sequence_name RESTART WITH 1;'... style SQL statements 164 # to reset sequence indices 165 for sequence_info in sequences: 166 table_name = sequence_info['table'] 167 column_name = sequence_info['column'] 168 if column_name and len(column_name)>0: 169 # sequence name in this case will be <table>_<column>_seq 170 sql.append("%s %s %s %s %s %s;" % \ 171 (style.SQL_KEYWORD('ALTER'), 172 style.SQL_KEYWORD('SEQUENCE'), 173 style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)), 174 style.SQL_KEYWORD('RESTART'), 175 style.SQL_KEYWORD('WITH'), 176 style.SQL_FIELD('1') 177 ) 178 ) 179 else: 180 # sequence name in this case will be <table>_id_seq 181 sql.append("%s %s %s %s %s %s;" % \ 182 (style.SQL_KEYWORD('ALTER'), 183 style.SQL_KEYWORD('SEQUENCE'), 184 style.SQL_FIELD('%s_id_seq' % table_name), 185 style.SQL_KEYWORD('RESTART'), 186 style.SQL_KEYWORD('WITH'), 187 style.SQL_FIELD('1') 188 ) 189 ) 190 return sql 191 else: 192 return [] 193 148 194 # Register these custom typecasts, because Django expects dates/times to be 149 195 # in Python's native (standard-library) datetime/time format, whereas psycopg 150 196 # use mx.DateTime by default. -
django/db/backends/sqlite3/base.py
148 148 def get_pk_default_value(): 149 149 return "NULL" 150 150 151 def get_sql_flush(style, tables, sequences): 152 """Return a list of SQL statements required to remove all data from 153 all tables in the database (without actually removing the tables 154 themselves) and put the database in an empty 'initial' state 155 156 """ 157 # NB: The generated SQL below is specific to SQLite 158 # Note: The DELETE FROM... SQL generated below works for SQLite databases 159 # because constraints don't exist 160 sql = ['%s %s %s;' % \ 161 (style.SQL_KEYWORD('DELETE'), 162 style.SQL_KEYWORD('FROM'), 163 style.SQL_FIELD(quote_name(table)) 164 ) for table in tables] 165 # Note: No requirement for reset of auto-incremented indices (cf. other 166 # get_sql_flush() implementations). Just return SQL at this point 167 return sql 168 151 169 def _sqlite_date_trunc(lookup_type, dt): 152 170 try: 153 171 dt = util.typecast_timestamp(dt) -
django/db/backends/mysql/base.py
183 183 def get_pk_default_value(): 184 184 return "DEFAULT" 185 185 186 def get_sql_flush(style, tables, sequences): 187 """Return a list of SQL statements required to remove all data from 188 all tables in the database (without actually removing the tables 189 themselves) and put the database in an empty 'initial' state 190 191 """ 192 # NB: The generated SQL below is specific to MySQL 193 # 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements 194 # to clear all tables of all data 195 if tables: 196 sql = ['%s %s;' % \ 197 (style.SQL_KEYWORD('TRUNCATE'), 198 style.SQL_FIELD(quote_name(table)) 199 ) for table in tables] 200 # 'ALTER TABLE table AUTO_INCREMENT = 1;'... style SQL statements 201 # to reset sequence indices 202 sql.extend(["%s %s %s %s %s;" % \ 203 (style.SQL_KEYWORD('ALTER'), 204 style.SQL_KEYWORD('TABLE'), 205 style.SQL_TABLE(quote_name(sequence['table'])), 206 style.SQL_KEYWORD('AUTO_INCREMENT'), 207 style.SQL_FIELD('= 1'), 208 ) for sequence in sequences]) 209 return sql 210 else: 211 return [] 212 186 213 OPERATOR_MAPPING = { 187 214 'exact': '= %s', 188 215 'iexact': 'LIKE %s', -
django/db/backends/oracle/base.py
117 117 def get_pk_default_value(): 118 118 return "DEFAULT" 119 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 # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements 126 # TODO - SQL not actually tested against Oracle yet! 127 # TODO - autoincrement indices reset required? See other get_sql_flush() implementations 128 sql = ['%s %s;' % \ 129 (style.SQL_KEYWORD('TRUNCATE'), 130 style.SQL_FIELD(quote_name(table)) 131 ) for table in tables] 132 133 120 134 OPERATOR_MAPPING = { 121 135 'exact': '= %s', 122 136 'iexact': 'LIKE %s', -
django/db/backends/postgresql_psycopg2/base.py
105 105 def get_pk_default_value(): 106 106 return "DEFAULT" 107 107 108 def get_sql_flush(style, tables, sequences): 109 """Return a list of SQL statements required to remove all data from 110 all tables in the database (without actually removing the tables 111 themselves) and put the database in an empty 'initial' state 112 """ 113 # Postgres can do 'TRUNCATE x, y, z...;'. In fact, it *has to* in order to be able to 114 # truncate tables referenced by a foreign key in any other table. The result is a 115 # single SQL TRUNCATE statement 116 if tables: 117 sql = ['%s %s;' % \ 118 (style.SQL_KEYWORD('TRUNCATE'), 119 style.SQL_FIELD(', '.join(quote_name(table) for table in tables)) 120 )] 121 # 'ALTER SEQUENCE sequence_name RESTART WITH 1;'... style SQL statements 122 # to reset sequence indices 123 for sequence in sequences: 124 table_name = sequence['table'] 125 column_name = sequence['column'] 126 if column_name and len(column_name) > 0: 127 # sequence name in this case will be <table>_<column>_seq 128 sql.append("%s %s %s %s %s %s;" % \ 129 (style.SQL_KEYWORD('ALTER'), 130 style.SQL_KEYWORD('SEQUENCE'), 131 style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)), 132 style.SQL_KEYWORD('RESTART'), 133 style.SQL_KEYWORD('WITH'), 134 style.SQL_FIELD('1') 135 ) 136 ) 137 else: 138 # sequence name in this case will be <table>_id_seq 139 sql.append("%s %s %s %s %s %s;" % \ 140 (style.SQL_KEYWORD('ALTER'), 141 style.SQL_KEYWORD('SEQUENCE'), 142 style.SQL_FIELD('%s_id_seq' % table_name), 143 style.SQL_KEYWORD('RESTART'), 144 style.SQL_KEYWORD('WITH'), 145 style.SQL_FIELD('1') 146 ) 147 ) 148 return sql 149 else: 150 return [] 151 108 152 OPERATOR_MAPPING = { 109 153 'exact': '= %s', 110 154 'iexact': 'ILIKE %s', -
django/db/backends/dummy/base.py
38 38 get_random_function_sql = complain 39 39 get_fulltext_search_sql = complain 40 40 get_drop_foreignkey_sql = complain 41 get_sql_flush = complain 42 41 43 OPERATOR_MAPPING = {} -
django/conf/global_settings.py
315 315 # The name of the database to use for testing purposes. 316 316 # If None, a name of 'test_' + DATABASE_NAME will be assumed 317 317 TEST_DATABASE_NAME = None 318 319 ############ 320 # FIXTURES # 321 ############ 322 323 # The list of directories to search for fixtures 324 FIXTURE_DIRS = () -
django/core/serializers/base.py
141 141 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 147 147 with the many-to-many data saved with the object. -
django/core/serializers/__init__.py
40 40 if not _serializers: 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): 45 50 if not _serializers: -
django/core/management.py
68 68 cursor = connection.cursor() 69 69 return get_introspection_module().get_table_list(cursor) 70 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 89 71 90 # If the foreign key points to an AutoField, a PositiveIntegerField or a 72 91 # PositiveSmallIntegerField, the foreign key should be an IntegerField, not the 73 92 # referred field type. Otherwise, the foreign key should be the same type of … … 330 349 get_sql_reset.help_doc = "Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s)." 331 350 get_sql_reset.args = APP_ARGS 332 351 333 def get_sql_initial_data_for_model(model): 352 def get_sql_flush(): 353 "Returns a list of the SQL statements used to flush the database" 354 from django.db import backend 355 statements = backend.get_sql_flush(style, _get_table_list(), _get_sequence_list()) 356 return statements 357 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." 358 get_sql_flush.args = '' 359 360 def get_custom_sql_for_model(model): 334 361 from django.db import models 335 362 from django.conf import settings 336 363 … … 357 384 358 385 return output 359 386 360 def get_ sql_initial_data(app):361 "Returns a list of the initial INSERTSQL statements for the given app."387 def get_custom_sql(app): 388 "Returns a list of the custom table modifying SQL statements for the given app." 362 389 from django.db.models import get_models 363 390 output = [] 364 391 … … 366 393 app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql')) 367 394 368 395 for model in app_models: 369 output.extend(get_ sql_initial_data_for_model(model))396 output.extend(get_custom_sql_for_model(model)) 370 397 371 398 return output 372 get_ sql_initial_data.help_doc = "Prints the initial INSERTSQL statements for the given app name(s)."373 get_ sql_initial_data.args = APP_ARGS399 get_custom_sql.help_doc = "Prints the custom table modifying SQL statements for the given app name(s)." 400 get_custom_sql.args = APP_ARGS 374 401 402 def get_sql_initial_data(apps): 403 "Returns a list of the initial INSERT SQL statements for the given app." 404 return style.ERROR("This action has been renamed. Try './manage.py sqlcustom %s'." % ' '.join(apps and apps or ['app1', 'app2'])) 405 get_sql_initial_data.help_doc = "RENAMED: see 'sqlcustom'" 406 get_sql_initial_data.args = '' 407 375 408 def get_sql_sequence_reset(app): 376 409 "Returns a list of the SQL statements to reset PostgreSQL sequences for the given app." 377 410 from django.db import backend, models … … 428 461 429 462 def get_sql_all(app): 430 463 "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module." 431 return get_sql_create(app) + get_ sql_initial_data(app) + get_sql_indexes(app)464 return get_sql_create(app) + get_custom_sql(app) + get_sql_indexes(app) 432 465 get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)." 433 466 get_sql_all.args = APP_ARGS 434 467 468 def _emit_post_sync_signal(created_models, verbosity, interactive): 469 from django.db import models 470 from django.dispatch import dispatcher 471 # Emit the post_sync signal for every application. 472 for app in models.get_apps(): 473 app_name = app.__name__.split('.')[-2] 474 if verbosity >= 2: 475 print "Running post-sync handlers for application", app_name 476 dispatcher.send(signal=models.signals.post_syncdb, sender=app, 477 app=app, created_models=created_models, 478 verbosity=verbosity, interactive=interactive) 479 435 480 def syncdb(verbosity=1, interactive=True): 436 481 "Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." 437 482 from django.db import connection, transaction, models, get_creation_module 438 from django.db.models import signals439 483 from django.conf import settings 440 from django.dispatch import dispatcher441 484 442 485 disable_termcolors() 443 486 … … 499 542 500 543 # Send the post_syncdb signal, so individual apps can do whatever they need 501 544 # to do at this point. 545 _emit_post_sync_signal(created_models, verbosity, interactive) 546 547 # Install custom SQL for the app (but only if this 548 # is a model we've just created) 502 549 for app in models.get_apps(): 503 app_name = app.__name__.split('.')[-2]504 if verbosity >= 2:505 print "Running post-sync handlers for application", app_name506 dispatcher.send(signal=signals.post_syncdb, sender=app,507 app=app, created_models=created_models,508 verbosity=verbosity, interactive=interactive)509 510 # Install initial data for the app (but only if this is a model we've511 # just created)512 550 for model in models.get_models(app): 513 551 if model in created_models: 514 initial_sql = get_sql_initial_data_for_model(model)515 if initial_sql:552 custom_sql = get_custom_sql_for_model(model) 553 if custom_sql: 516 554 if verbosity >= 1: 517 print "Installing initial datafor %s.%s model" % (app_name, model._meta.object_name)555 print "Installing custom SQL for %s.%s model" % (app_name, model._meta.object_name) 518 556 try: 519 for sql in initial_sql:557 for sql in custom_sql: 520 558 cursor.execute(sql) 521 559 except Exception, e: 522 sys.stderr.write("Failed to install initial SQL datafor %s.%s model: %s" % \560 sys.stderr.write("Failed to install custom SQL for %s.%s model: %s" % \ 523 561 (app_name, model._meta.object_name, e)) 524 562 transaction.rollback_unless_managed() 525 563 else: … … 544 582 else: 545 583 transaction.commit_unless_managed() 546 584 547 syncdb.args = '' 585 # Install the 'initialdata' fixture, using format discovery 586 load_data(['initial_data'], verbosity=verbosity) 587 syncdb.help_doc = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." 588 syncdb.args = '[--verbosity] [--interactive]' 548 589 549 590 def get_admin_index(app): 550 591 "Returns admin-index template snippet (in list form) for the given app." … … 597 638 print '\n'.join(output) 598 639 diffsettings.args = "" 599 640 600 def install(app):601 "Executes the equivalent of 'get_sql_all' in the current database."602 from django.db import connection, transaction603 604 app_name = app.__name__.split('.')[-2]605 606 disable_termcolors()607 608 # First, try validating the models.609 _check_for_validation_errors(app)610 611 sql_list = get_sql_all(app)612 613 try:614 cursor = connection.cursor()615 for sql in sql_list:616 cursor.execute(sql)617 except Exception, e:618 sys.stderr.write(style.ERROR("""Error: %s couldn't be installed. Possible reasons:619 * The database isn't running or isn't configured correctly.620 * At least one of the database tables already exists.621 * The SQL was invalid.622 Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this command wasn't able to run.623 The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n')624 transaction.rollback_unless_managed()625 sys.exit(1)626 transaction.commit_unless_managed()627 install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database."628 install.args = APP_ARGS629 630 641 def reset(app, interactive=True): 631 642 "Executes the equivalent of 'get_sql_reset' in the current database." 632 643 from django.db import connection, transaction … … 668 679 else: 669 680 print "Reset cancelled." 670 681 reset.help_doc = "Executes ``sqlreset`` for the given app(s) in the current database." 671 reset.args = APP_ARGS682 reset.args = '[--interactive]' + APP_ARGS 672 683 684 def flush(verbosity=1, interactive=True): 685 "Returns all tables in the database to the same state they were in immediately after syncdb." 686 from django.conf import settings 687 from django.db import connection, transaction, models 688 from django.dispatch import dispatcher 689 690 disable_termcolors() 691 692 # First, try validating the models. 693 _check_for_validation_errors() 694 695 # Import the 'management' module within each installed app, to register 696 # dispatcher events. 697 for app_name in settings.INSTALLED_APPS: 698 try: 699 __import__(app_name + '.management', {}, {}, ['']) 700 except ImportError: 701 pass 702 703 sql_list = get_sql_flush() 704 705 if interactive: 706 confirm = raw_input(""" 707 You have requested a flush of the database. 708 This will IRREVERSIBLY DESTROY all data currently in the database, 709 and return each table to the state it was in after syncdb. 710 Are you sure you want to do this? 711 712 Type 'yes' to continue, or 'no' to cancel: """) 713 else: 714 confirm = 'yes' 715 716 if confirm == 'yes': 717 try: 718 cursor = connection.cursor() 719 for sql in sql_list: 720 cursor.execute(sql) 721 except Exception, e: 722 sys.stderr.write(style.ERROR("""Error: Database %s couldn't be flushed. Possible reasons: 723 * The database isn't running or isn't configured correctly. 724 * At least one of the expected database tables doesn't exist. 725 * The SQL was invalid. 726 Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run. 727 The full error: """ % settings.DATABASE_NAME + style.ERROR_OUTPUT(str(e)) + '\n')) 728 transaction.rollback_unless_managed() 729 sys.exit(1) 730 transaction.commit_unless_managed() 731 732 # Emit the post sync signal. This allows individual 733 # applications to respond as if the database had been 734 # sync'd from scratch. 735 _emit_post_sync_signal(models.get_models(), verbosity, interactive) 736 737 # Reinstall the initial_data fixture 738 load_data(['initial_data'], verbosity=verbosity) 739 740 else: 741 print "Flush cancelled." 742 flush.help_doc = "Executes ``sqlflush`` on the current database." 743 flush.args = '[--verbosity] [--interactive]' 744 673 745 def _start_helper(app_or_project, name, directory, other_name=''): 674 746 other = {'project': 'app', 'app': 'project'}[app_or_project] 675 747 if not _is_valid_dir_name(name): … … 751 823 yield "# * Make sure each model has one field with primary_key=True" 752 824 yield "# Feel free to rename the models, but don't rename db_table values or field names." 753 825 yield "#" 754 yield "# Also note: You'll have to insert the output of 'django-admin.py sql initialdata[appname]'"826 yield "# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]'" 755 827 yield "# into your database." 756 828 yield '' 757 829 yield 'from django.db import models' … … 1239 1311 test.help_doc = 'Runs the test suite for the specified applications, or the entire site if no apps are specified' 1240 1312 test.args = '[--verbosity] ' + APP_ARGS 1241 1313 1314 def load_data(fixture_labels, verbosity=1): 1315 "Installs the provided fixture file(s) as data in the database." 1316 from django.db.models import get_apps 1317 from django.core import serializers 1318 from django.db import transaction 1319 from django.conf import settings 1320 import sys 1321 1322 # Keep a count of the installed objects and fixtures 1323 count = [0,0] 1324 1325 humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path' 1326 1327 # Start transaction management. All fixtures are installed in a 1328 # single transaction to ensure that all references are resolved. 1329 transaction.enter_transaction_management() 1330 transaction.managed(True) 1331 1332 app_fixtures = [os.path.join(os.path.dirname(app.__file__),'fixtures') for app in get_apps()] 1333 for fixture_label in fixture_labels: 1334 if verbosity > 0: 1335 print "Loading '%s' fixtures..." % fixture_label 1336 for fixture_dir in app_fixtures + list(settings.FIXTURE_DIRS) + ['']: 1337 if verbosity > 1: 1338 print "Checking %s for fixtures..." % humanize(fixture_dir) 1339 try: 1340 fixture_name, format = fixture_label.rsplit('.', 1) 1341 formats = [format] 1342 except ValueError: 1343 fixture_name = fixture_label 1344 formats = serializers.get_serializer_formats() 1345 1346 label_found = False 1347 for format in formats: 1348 serializer = serializers.get_serializer(format) 1349 if verbosity > 1: 1350 print "Trying %s for %s fixture '%s'..." % \ 1351 (humanize(fixture_dir), format, fixture_name) 1352 try: 1353 full_path = os.path.join(fixture_dir, '.'.join([fixture_name, format])) 1354 fixture = open(full_path, 'r') 1355 if label_found: 1356 fixture.close() 1357 print style.ERROR("Multiple fixtures named '%s' in %s. Aborting." % 1358 (fixture_name, humanize(fixture_dir))) 1359 transaction.rollback() 1360 transaction.leave_transaction_management() 1361 return 1362 else: 1363 count[1] += 1 1364 if verbosity > 0: 1365 print "Installing %s fixture '%s' from %s." % \ 1366 (format, fixture_name, humanize(fixture_dir)) 1367 try: 1368 objects = serializers.deserialize(format, fixture) 1369 for obj in objects: 1370 count[0] += 1 1371 obj.save() 1372 label_found = True 1373 except Exception, e: 1374 fixture.close() 1375 sys.stderr.write( 1376 style.ERROR("Problem installing fixture '%s': %s\n" % 1377 (full_path, str(e)))) 1378 transaction.rollback() 1379 transaction.leave_transaction_management() 1380 return 1381 fixture.close() 1382 except: 1383 if verbosity > 1: 1384 print "No %s fixture '%s' in %s." % \ 1385 (format, fixture_name, humanize(fixture_dir)) 1386 if count[0] == 0: 1387 if verbosity > 0: 1388 print "No fixtures found." 1389 else: 1390 if verbosity > 0: 1391 print "Installed %d object(s) from %d fixture(s)" % tuple(count) 1392 transaction.commit() 1393 transaction.leave_transaction_management() 1394 1395 load_data.help_doc = 'Installs the named fixture(s) in the database' 1396 load_data.args = "[--verbosity] fixture, fixture, ..." 1397 1398 def dump_data(app_labels, format='json'): 1399 "Output the current contents of the database as a fixture of the given format" 1400 from django.db.models import get_app, get_apps, get_models 1401 from django.core import serializers 1402 1403 if len(app_labels) == 0: 1404 app_list = get_apps() 1405 else: 1406 app_list = [get_app(app_label) for app_label in app_labels] 1407 1408 # Check that the serialization format exists; this is a shortcut to 1409 # avoid collating all the objects and _then_ failing. 1410 try: 1411 serializers.get_serializer(format) 1412 except KeyError: 1413 sys.stderr.write(style.ERROR("Unknown serialization format: %s\n" % format)) 1414 1415 objects = [] 1416 for app in app_list: 1417 for model in get_models(app): 1418 objects.extend(model.objects.all()) 1419 try: 1420 print serializers.serialize(format, objects) 1421 except Exception, e: 1422 sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e)) 1423 dump_data.help_doc = 'Output the contents of the database as a fixture of the given format' 1424 dump_data.args = '[--format]' + APP_ARGS 1425 1242 1426 # Utilities for command-line script 1243 1427 1244 1428 DEFAULT_ACTION_MAPPING = { … … 1246 1430 'createcachetable' : createcachetable, 1247 1431 'dbshell': dbshell, 1248 1432 'diffsettings': diffsettings, 1433 'dumpdata': dump_data, 1434 'flush': flush, 1249 1435 'inspectdb': inspectdb, 1250 ' install': install,1436 'loaddata': load_data, 1251 1437 'reset': reset, 1252 1438 'runfcgi': runfcgi, 1253 1439 'runserver': runserver, … … 1255 1441 'sql': get_sql_create, 1256 1442 'sqlall': get_sql_all, 1257 1443 'sqlclear': get_sql_delete, 1444 'sqlcustom': get_custom_sql, 1445 'sqlflush': get_sql_flush, 1258 1446 'sqlindexes': get_sql_indexes, 1259 1447 'sqlinitialdata': get_sql_initial_data, 1260 1448 'sqlreset': get_sql_reset, … … 1271 1459 'createcachetable', 1272 1460 'dbshell', 1273 1461 'diffsettings', 1274 'install',1275 1462 'reset', 1276 1463 'sqlindexes', 1277 1464 'syncdb', … … 1318 1505 help='Tells Django to NOT prompt the user for input of any kind.') 1319 1506 parser.add_option('--noreload', action='store_false', dest='use_reloader', default=True, 1320 1507 help='Tells Django to NOT use the auto-reloader when running the development server.') 1508 parser.add_option('--format', default='json', dest='format', 1509 help='Specifies the output serialization format for fixtures') 1321 1510 parser.add_option('--verbosity', action='store', dest='verbosity', default='1', 1322 1511 type='choice', choices=['0', '1', '2'], 1323 1512 help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), … … 1351 1540 action_mapping[action](options.plain is True) 1352 1541 elif action in ('validate', 'diffsettings', 'dbshell'): 1353 1542 action_mapping[action]() 1354 elif action == 'syncdb':1543 elif action in ('flush', 'syncdb'): 1355 1544 action_mapping[action](int(options.verbosity), options.interactive) 1356 1545 elif action == 'inspectdb': 1357 1546 try: … … 1365 1554 action_mapping[action](args[1]) 1366 1555 except IndexError: 1367 1556 parser.print_usage_and_exit() 1368 elif action == 'test':1557 elif action in ('test', 'loaddata'): 1369 1558 try: 1370 1559 action_mapping[action](args[1:], int(options.verbosity)) 1371 1560 except IndexError: 1372 1561 parser.print_usage_and_exit() 1562 elif action == 'dumpdata': 1563 try: 1564 action_mapping[action](args[1:], options.format) 1565 except IndexError: 1566 parser.print_usage_and_exit() 1373 1567 elif action in ('startapp', 'startproject'): 1374 1568 try: 1375 1569 name = args[1] … … 1388 1582 action_mapping[action](addr, port, options.use_reloader, options.admin_media_path) 1389 1583 elif action == 'runfcgi': 1390 1584 action_mapping[action](args[1:]) 1585 elif action == 'sqlinitialdata': 1586 print action_mapping[action](args[1:]) 1587 elif action == 'sqlflush': 1588 print '\n'.join(action_mapping[action]()) 1391 1589 else: 1392 1590 from django.db import models 1393 1591 validate(silent_success=True) -
tests/modeltests/fixtures/fixtures/fixture1.json
Property changes on: tests/modeltests/fixtures ___________________________________________________________________ Name: svn:ignore + *.pyc Property changes on: tests/modeltests/fixtures/fixtures ___________________________________________________________________ Name: svn:ignore + *.pyc
1 [ 2 { 3 "pk": "2", 4 "model": "fixtures.article", 5 "fields": { 6 "headline": "Poker has no place on ESPN", 7 "pub_date": "2006-06-16 12:00:00" 8 } 9 }, 10 { 11 "pk": "3", 12 "model": "fixtures.article", 13 "fields": { 14 "headline": "Time to reform copyright", 15 "pub_date": "2006-06-16 13:00:00" 16 } 17 } 18 ] 19 No newline at end of file -
tests/modeltests/fixtures/fixtures/fixture2.json
1 [ 2 { 3 "pk": "3", 4 "model": "fixtures.article", 5 "fields": { 6 "headline": "Copyright is fine the way it is", 7 "pub_date": "2006-06-16 14:00:00" 8 } 9 }, 10 { 11 "pk": "4", 12 "model": "fixtures.article", 13 "fields": { 14 "headline": "Django conquers world!", 15 "pub_date": "2006-06-16 15:00:00" 16 } 17 } 18 ] 19 No newline at end of file -
tests/modeltests/fixtures/fixtures/fixture2.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="2" model="fixtures.article"> 4 <field type="CharField" name="headline">Poker on TV is great!</field> 5 <field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field> 6 </object> 7 <object pk="5" model="fixtures.article"> 8 <field type="CharField" name="headline">XML identified as leading cause of cancer</field> 9 <field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field> 10 </object> 11 </django-objects> 12 No newline at end of file -
tests/modeltests/fixtures/fixtures/fixture3.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <django-objects version="1.0"> 3 <object pk="2" model="fixtures.article"> 4 <field type="CharField" name="headline">Poker on TV is great!</field> 5 <field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field> 6 </object> 7 <object pk="5" model="fixtures.article"> 8 <field type="CharField" name="headline">XML identified as leading cause of cancer</field> 9 <field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field> 10 </object> 11 </django-objects> 12 No newline at end of file -
tests/modeltests/fixtures/models.py
1 """ 2 39. Fixtures. 3 4 Fixtures are a way of loading data into the database in bulk. Fixure data 5 can be stored in any serializable format (including JSON and XML). Fixtures 6 are identified by name, and are stored in either a directory named 'fixtures' 7 in the application directory, on in one of the directories named in the 8 FIXTURE_DIRS setting. 9 """ 10 11 from django.db import models 12 13 class Article(models.Model): 14 headline = models.CharField(maxlength=100, default='Default headline') 15 pub_date = models.DateTimeField() 16 17 def __str__(self): 18 return self.headline 19 20 class Meta: 21 ordering = ('-pub_date', 'headline') 22 23 __test__ = {'API_TESTS': """ 24 >>> from django.core import management 25 >>> from django.db.models import get_app 26 27 # Syncdb introduces 1 initial data object from initial_data.json. 28 >>> Article.objects.all() 29 [<Article: Python program becomes self aware>] 30 31 # Load fixture 1. Single JSON file, with two objects. 32 >>> management.load_data(['fixture1.json'], verbosity=0) 33 >>> Article.objects.all() 34 [<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] 35 36 # Load fixture 2. JSON file imported by default. Overwrites some existing objects 37 >>> management.load_data(['fixture2.json'], verbosity=0) 38 >>> Article.objects.all() 39 [<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>] 40 41 # Load fixture 3, XML format. 42 >>> management.load_data(['fixture3.xml'], verbosity=0) 43 >>> Article.objects.all() 44 [<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>] 45 46 # Load a fixture that doesn't exist 47 >>> management.load_data(['unknown.json'], verbosity=0) 48 49 # object list is unaffected 50 >>> Article.objects.all() 51 [<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>] 52 53 # Reset the database representation of this app. This will delete all data. 54 >>> management.flush(verbosity=0, interactive=False) 55 >>> Article.objects.all() 56 [<Article: Python program becomes self aware>] 57 58 # Load fixture 1 again, using format discovery 59 >>> management.load_data(['fixture1'], verbosity=0) 60 >>> Article.objects.all() 61 [<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] 62 63 # Try to load fixture 2 using format discovery; this will fail 64 # because there are two fixture2's in the fixtures directory 65 >>> management.load_data(['fixture2'], verbosity=0) # doctest: +ELLIPSIS 66 Multiple fixtures named 'fixture2' in '.../fixtures'. Aborting. 67 68 >>> Article.objects.all() 69 [<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] 70 71 # Dump the current contents of the database as a JSON fixture 72 >>> management.dump_data(['fixtures'], format='json') 73 [{"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"}}] 74 """} 75 76 from django.test import TestCase 77 78 class SampleTestCase(TestCase): 79 fixtures = ['fixture1.json', 'fixture2.json'] 80 81 def testClassFixtures(self): 82 "Check that test case has installed 4 fixture objects" 83 self.assertEqual(Article.objects.count(), 4) 84 self.assertEquals(str(Article.objects.all()), "[<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>]") -
tests/modeltests/test_client/management.py
1 from django.dispatch import dispatcher2 from django.db.models import signals3 import models as test_client_app4 from django.contrib.auth.models import User5 6 def setup_test(app, created_models, verbosity):7 # Create a user account for the login-based tests8 User.objects.create_user('testclient','testclient@example.com', 'password')9 10 dispatcher.connect(setup_test, sender=test_client_app, signal=signals.post_syncdb) -
tests/modeltests/test_client/fixtures/testdata.json
Property changes on: tests/modeltests/test_client/fixtures ___________________________________________________________________ Name: svn:ignore + *.pyc
1 [ 2 { 3 "pk": "1", 4 "model": "auth.user", 5 "fields": { 6 "username": "testclient", 7 "first_name": "Test", 8 "last_name": "Client", 9 "is_active": true, 10 "is_superuser": false, 11 "is_staff": false, 12 "last_login": "2006-12-17 07:03:31", 13 "groups": [], 14 "user_permissions": [], 15 "password": "sha1$6efc0$f93efe9fd7542f25a7be94871ea45aa95de57161", 16 "email": "testclient@example.com", 17 "date_joined": "2006-12-17 07:03:31" 18 } 19 } 20 ] 21 No newline at end of file -
tests/modeltests/test_client/models.py
19 19 rather than the HTML rendered to the end-user. 20 20 21 21 """ 22 from django.test.client import Client 23 import unittest 22 from django.test import Client, TestCase 24 23 25 class ClientTest(unittest.TestCase): 24 class ClientTest(TestCase): 25 fixtures = ['testdata.json'] 26 26 27 def setUp(self): 27 28 "Set up test environment" 28 29 self.client = Client() -
tests/urls.py
6 6 7 7 # Always provide the auth system login and logout views 8 8 (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}), 9 (r'^accounts/logout/$', 'django.contrib.auth.views.log in'),9 (r'^accounts/logout/$', 'django.contrib.auth.views.logout'), 10 10 )