diff -r ed4d2e6277b2 django/core/management/commands/loaddata.py
a
|
b
|
|
28 | 28 | |
29 | 29 | verbosity = int(options.get('verbosity', 1)) |
30 | 30 | show_traceback = options.get('traceback', False) |
| 31 | no_commit = options.get('no_commit', False) |
31 | 32 | |
32 | 33 | # Keep a count of the installed objects and fixtures |
33 | 34 | fixture_count = 0 |
… |
… |
|
44 | 45 | |
45 | 46 | # Start transaction management. All fixtures are installed in a |
46 | 47 | # single transaction to ensure that all references are resolved. |
47 | | transaction.commit_unless_managed() |
48 | | transaction.enter_transaction_management() |
49 | | transaction.managed(True) |
| 48 | if not no_commit: |
| 49 | transaction.commit_unless_managed() |
| 50 | transaction.enter_transaction_management() |
| 51 | transaction.managed(True) |
50 | 52 | |
51 | 53 | app_fixtures = [os.path.join(os.path.dirname(app.__file__), 'fixtures') for app in get_apps()] |
52 | 54 | for fixture_label in fixture_labels: |
… |
… |
|
133 | 135 | (format, fixture_name, humanize(fixture_dir)) |
134 | 136 | |
135 | 137 | |
136 | | # If any of the fixtures we loaded contain 0 objects, assume that an |
| 138 | # If any of the fixtures we loaded contain 0 objects, assume that an |
137 | 139 | # error was encountered during fixture loading. |
138 | 140 | if 0 in objects_per_fixture: |
139 | 141 | sys.stderr.write( |
… |
… |
|
142 | 144 | transaction.rollback() |
143 | 145 | transaction.leave_transaction_management() |
144 | 146 | return |
145 | | |
146 | | # If we found even one object in a fixture, we need to reset the |
| 147 | |
| 148 | # If we found even one object in a fixture, we need to reset the |
147 | 149 | # database sequences. |
148 | 150 | if object_count > 0: |
149 | 151 | sequence_sql = connection.ops.sequence_reset_sql(self.style, models) |
… |
… |
|
152 | 154 | print "Resetting sequences" |
153 | 155 | for line in sequence_sql: |
154 | 156 | cursor.execute(line) |
155 | | |
156 | | transaction.commit() |
157 | | transaction.leave_transaction_management() |
| 157 | |
| 158 | if not no_commit: |
| 159 | transaction.commit() |
| 160 | transaction.leave_transaction_management() |
158 | 161 | |
159 | 162 | if object_count == 0: |
160 | 163 | if verbosity > 1: |
… |
… |
|
162 | 165 | else: |
163 | 166 | if verbosity > 0: |
164 | 167 | print "Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count) |
165 | | |
| 168 | |
166 | 169 | # Close the DB connection. This is required as a workaround for an |
167 | 170 | # edge case in MySQL: if the same connection is used to |
168 | 171 | # create tables, load data, and query, the query can return |
169 | 172 | # incorrect results. See Django #7572, MySQL #37735. |
170 | | connection.close() |
| 173 | if not no_commit: |
| 174 | connection.close() |
diff -r ed4d2e6277b2 django/test/__init__.py
a
|
b
|
|
3 | 3 | """ |
4 | 4 | |
5 | 5 | from django.test.client import Client |
6 | | from django.test.testcases import TestCase |
| 6 | from django.test.testcases import TestCase, TransactionTestCase |
diff -r ed4d2e6277b2 django/test/testcases.py
a
|
b
|
|
55 | 55 | """Tries to do a 'xml-comparision' of want and got. Plain string |
56 | 56 | comparision doesn't always work because, for example, attribute |
57 | 57 | ordering should not be important. |
58 | | |
| 58 | |
59 | 59 | Based on http://codespeak.net/svn/lxml/trunk/src/lxml/doctestcompare.py |
60 | 60 | """ |
61 | 61 | _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+') |
… |
… |
|
102 | 102 | wrapper = '<root>%s</root>' |
103 | 103 | want = wrapper % want |
104 | 104 | got = wrapper % got |
105 | | |
| 105 | |
106 | 106 | # Parse the want and got strings, and compare the parsings. |
107 | 107 | try: |
108 | 108 | want_root = parseString(want).firstChild |
… |
… |
|
169 | 169 | # side effects on other tests. |
170 | 170 | transaction.rollback_unless_managed() |
171 | 171 | |
172 | | class TestCase(unittest.TestCase): |
| 172 | def run(self, test, compileflags=None, out=None, clear_globs=True): |
| 173 | """ |
| 174 | Wraps the parent run() and encloses it in a transaction. |
| 175 | """ |
| 176 | transaction.enter_transaction_management() |
| 177 | transaction.managed(True) |
| 178 | result = doctest.DocTestRunner.run(self, test, compileflags, out, clear_globs) |
| 179 | transaction.rollback() |
| 180 | transaction.leave_transaction_management() |
| 181 | return result |
| 182 | |
| 183 | class TransactionTestCase(unittest.TestCase): |
173 | 184 | def _pre_setup(self): |
174 | 185 | """Performs any pre-test setup. This includes: |
175 | 186 | |
176 | 187 | * Flushing the database. |
177 | | * If the Test Case class has a 'fixtures' member, installing the |
| 188 | * If the Test Case class has a 'fixtures' member, installing the |
178 | 189 | named fixtures. |
179 | 190 | * If the Test Case class has a 'urls' member, replace the |
180 | 191 | ROOT_URLCONF with it. |
181 | 192 | * Clearing the mail test outbox. |
182 | 193 | """ |
| 194 | self._fixture_setup() |
| 195 | self._urlconf_setup() |
| 196 | mail.outbox = [] |
| 197 | |
| 198 | def _fixture_setup(self): |
183 | 199 | call_command('flush', verbosity=0, interactive=False) |
184 | 200 | if hasattr(self, 'fixtures'): |
185 | 201 | # We have to use this slightly awkward syntax due to the fact |
186 | 202 | # that we're using *args and **kwargs together. |
187 | 203 | call_command('loaddata', *self.fixtures, **{'verbosity': 0}) |
| 204 | |
| 205 | def _urlconf_setup(self): |
188 | 206 | if hasattr(self, 'urls'): |
189 | 207 | self._old_root_urlconf = settings.ROOT_URLCONF |
190 | 208 | settings.ROOT_URLCONF = self.urls |
191 | 209 | clear_url_caches() |
192 | | mail.outbox = [] |
193 | 210 | |
194 | 211 | def __call__(self, result=None): |
195 | 212 | """ |
… |
… |
|
206 | 223 | import sys |
207 | 224 | result.addError(self, sys.exc_info()) |
208 | 225 | return |
209 | | super(TestCase, self).__call__(result) |
| 226 | super(TransactionTestCase, self).__call__(result) |
210 | 227 | try: |
211 | 228 | self._post_teardown() |
212 | 229 | except (KeyboardInterrupt, SystemExit): |
… |
… |
|
221 | 238 | |
222 | 239 | * Putting back the original ROOT_URLCONF if it was changed. |
223 | 240 | """ |
| 241 | self._fixture_teardown() |
| 242 | self._urlconf_teardown() |
| 243 | |
| 244 | def _fixture_teardown(self): |
| 245 | pass |
| 246 | |
| 247 | def _urlconf_teardown(self): |
224 | 248 | if hasattr(self, '_old_root_urlconf'): |
225 | 249 | settings.ROOT_URLCONF = self._old_root_urlconf |
226 | 250 | clear_url_caches() |
… |
… |
|
354 | 378 | self.failIf(template_name in template_names, |
355 | 379 | (u"Template '%s' was used unexpectedly in rendering the" |
356 | 380 | u" response") % template_name) |
| 381 | |
| 382 | class TestCase(TransactionTestCase): |
| 383 | """ |
| 384 | Does basically the same as TransactionTestCase, but surrounds every test |
| 385 | with a transaction. You have to use TransactionTestCase, if you need |
| 386 | transaction management inside a test. |
| 387 | """ |
| 388 | def _fixture_setup(self): |
| 389 | transaction.enter_transaction_management() |
| 390 | transaction.managed(True) |
| 391 | |
| 392 | if hasattr(self, 'fixtures'): |
| 393 | call_command('loaddata', *self.fixtures, **{ |
| 394 | 'verbosity': 0, |
| 395 | 'no_commit': True |
| 396 | }) |
| 397 | |
| 398 | def _fixture_teardown(self): |
| 399 | transaction.rollback() |
| 400 | transaction.leave_transaction_management() |