diff -r ed4d2e6277b2 django/contrib/auth/tests/views.py
--- a/django/contrib/auth/tests/views.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/django/contrib/auth/tests/views.py	Fri Aug 08 00:38:24 2008 +0100
@@ -1,10 +1,10 @@
 
 import re
 from django.contrib.auth.models import User
-from django.test import TestCase
+from django.test import TransactionTestCase
 from django.core import mail
 
-class PasswordResetTest(TestCase):
+class PasswordResetTest(TransactionTestCase):
     fixtures = ['authtestdata.json']
     urls = 'django.contrib.auth.urls'
     
diff -r ed4d2e6277b2 django/core/management/commands/loaddata.py
--- a/django/core/management/commands/loaddata.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/django/core/management/commands/loaddata.py	Fri Aug 08 00:38:24 2008 +0100
@@ -28,6 +28,7 @@
 
         verbosity = int(options.get('verbosity', 1))
         show_traceback = options.get('traceback', False)
+        no_commit = options.get('no_commit', False)
 
         # Keep a count of the installed objects and fixtures
         fixture_count = 0
@@ -44,9 +45,10 @@
 
         # Start transaction management. All fixtures are installed in a
         # single transaction to ensure that all references are resolved.
-        transaction.commit_unless_managed()
-        transaction.enter_transaction_management()
-        transaction.managed(True)
+        if not no_commit:
+            transaction.commit_unless_managed()
+            transaction.enter_transaction_management()
+            transaction.managed(True)
 
         app_fixtures = [os.path.join(os.path.dirname(app.__file__), 'fixtures') for app in get_apps()]
         for fixture_label in fixture_labels:
@@ -133,7 +135,7 @@
                                 (format, fixture_name, humanize(fixture_dir))
 
 
-        # If any of the fixtures we loaded contain 0 objects, assume that an 
+        # If any of the fixtures we loaded contain 0 objects, assume that an
         # error was encountered during fixture loading.
         if 0 in objects_per_fixture:
             sys.stderr.write(
@@ -142,8 +144,8 @@
             transaction.rollback()
             transaction.leave_transaction_management()
             return
-            
-        # If we found even one object in a fixture, we need to reset the 
+
+        # If we found even one object in a fixture, we need to reset the
         # database sequences.
         if object_count > 0:
             sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
@@ -152,9 +154,10 @@
                     print "Resetting sequences"
                 for line in sequence_sql:
                     cursor.execute(line)
-            
-        transaction.commit()
-        transaction.leave_transaction_management()
+
+        if not no_commit:
+            transaction.commit()
+            transaction.leave_transaction_management()
 
         if object_count == 0:
             if verbosity > 1:
@@ -162,9 +165,10 @@
         else:
             if verbosity > 0:
                 print "Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count)
-                
+
         # Close the DB connection. This is required as a workaround for an
         # edge case in MySQL: if the same connection is used to
         # create tables, load data, and query, the query can return
         # incorrect results. See Django #7572, MySQL #37735.
-        connection.close()
+        if not no_commit:
+            connection.close()
diff -r ed4d2e6277b2 django/test/__init__.py
--- a/django/test/__init__.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/django/test/__init__.py	Fri Aug 08 00:38:24 2008 +0100
@@ -3,4 +3,4 @@
 """
 
 from django.test.client import Client
-from django.test.testcases import TestCase
+from django.test.testcases import TestCase, TransactionTestCase
diff -r ed4d2e6277b2 django/test/testcases.py
--- a/django/test/testcases.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/django/test/testcases.py	Fri Aug 08 00:38:24 2008 +0100
@@ -55,7 +55,7 @@
         """Tries to do a 'xml-comparision' of want and got.  Plain string
         comparision doesn't always work because, for example, attribute
         ordering should not be important.
-        
+
         Based on http://codespeak.net/svn/lxml/trunk/src/lxml/doctestcompare.py
         """
         _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+')
@@ -102,7 +102,7 @@
             wrapper = '<root>%s</root>'
             want = wrapper % want
             got = wrapper % got
-            
+
         # Parse the want and got strings, and compare the parsings.
         try:
             want_root = parseString(want).firstChild
@@ -169,27 +169,47 @@
         # side effects on other tests.
         transaction.rollback_unless_managed()
 
-class TestCase(unittest.TestCase):
+    def run(self, test, compileflags=None, out=None, clear_globs=True):
+        """
+        Wraps the parent run() and encloses it in a transaction.
+        """
+        tests_use_transactions = test.docstring.strip().startswith('# TESTS USE TRANSACTIONS')
+        if not tests_use_transactions:
+            transaction.enter_transaction_management()
+            transaction.managed(True)
+        result = doctest.DocTestRunner.run(self, test, compileflags, out, clear_globs)
+        if not tests_use_transactions:
+            transaction.rollback()
+            transaction.leave_transaction_management()
+        return result
+
+class TransactionTestCase(unittest.TestCase):
     def _pre_setup(self):
         """Performs any pre-test setup. This includes:
 
             * Flushing the database.
-            * If the Test Case class has a 'fixtures' member, installing the 
+            * If the Test Case class has a 'fixtures' member, installing the
               named fixtures.
             * If the Test Case class has a 'urls' member, replace the
               ROOT_URLCONF with it.
             * Clearing the mail test outbox.
         """
+        self._fixture_setup()
+        self._urlconf_setup()
+        mail.outbox = []
+
+    def _fixture_setup(self):
         call_command('flush', verbosity=0, interactive=False)
         if hasattr(self, 'fixtures'):
             # We have to use this slightly awkward syntax due to the fact
             # that we're using *args and **kwargs together.
             call_command('loaddata', *self.fixtures, **{'verbosity': 0})
+
+    def _urlconf_setup(self):
         if hasattr(self, 'urls'):
             self._old_root_urlconf = settings.ROOT_URLCONF
             settings.ROOT_URLCONF = self.urls
             clear_url_caches()
-        mail.outbox = []
 
     def __call__(self, result=None):
         """
@@ -206,7 +226,7 @@
             import sys
             result.addError(self, sys.exc_info())
             return
-        super(TestCase, self).__call__(result)
+        super(TransactionTestCase, self).__call__(result)
         try:
             self._post_teardown()
         except (KeyboardInterrupt, SystemExit):
@@ -221,6 +241,13 @@
 
             * Putting back the original ROOT_URLCONF if it was changed.
         """
+        self._fixture_teardown()
+        self._urlconf_teardown()
+
+    def _fixture_teardown(self):
+        pass
+
+    def _urlconf_teardown(self):
         if hasattr(self, '_old_root_urlconf'):
             settings.ROOT_URLCONF = self._old_root_urlconf
             clear_url_caches()
@@ -354,3 +381,23 @@
         self.failIf(template_name in template_names,
             (u"Template '%s' was used unexpectedly in rendering the"
              u" response") % template_name)
+
+class TestCase(TransactionTestCase):
+    """
+    Does basically the same as TransactionTestCase, but surrounds every test
+    with a transaction. You have to use TransactionTestCase, if you need
+    transaction management inside a test.
+    """
+    def _fixture_setup(self):
+        transaction.enter_transaction_management()
+        transaction.managed(True)
+
+        if hasattr(self, 'fixtures'):
+            call_command('loaddata', *self.fixtures, **{
+                                                        'verbosity': 0,
+                                                        'no_commit': True
+                                                        })
+
+    def _fixture_teardown(self):
+        transaction.rollback()
+        transaction.leave_transaction_management()
diff -r ed4d2e6277b2 tests/modeltests/fixtures/models.py
--- a/tests/modeltests/fixtures/models.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/tests/modeltests/fixtures/models.py	Fri Aug 08 00:38:24 2008 +0100
@@ -22,6 +22,7 @@
         ordering = ('-pub_date', 'headline')
 
 __test__ = {'API_TESTS': """
+# TESTS USE TRANSACTIONS
 >>> from django.core import management
 >>> from django.db.models import get_app
 
@@ -92,4 +93,4 @@
     def testClassFixtures(self):
         "Check that test case has installed 4 fixture objects"
         self.assertEqual(Article.objects.count(), 4)
-        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>]")
+        self.assertEquals(str(Article.objects.order_by('headline')), "[<Article: Copyright is fine the way it is>, <Article: Django conquers world!>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>]")
diff -r ed4d2e6277b2 tests/modeltests/test_client/models.py
--- a/tests/modeltests/test_client/models.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/tests/modeltests/test_client/models.py	Fri Aug 08 00:38:24 2008 +0100
@@ -20,10 +20,10 @@
 rather than the HTML rendered to the end-user.
 
 """
-from django.test import Client, TestCase
+from django.test import Client, TransactionTestCase
 from django.core import mail
 
-class ClientTest(TestCase):
+class ClientTest(TransactionTestCase):
     fixtures = ['testdata.json']
 
     def test_get_view(self):
diff -r ed4d2e6277b2 tests/regressiontests/admin_views/tests.py
--- a/tests/regressiontests/admin_views/tests.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/tests/regressiontests/admin_views/tests.py	Fri Aug 08 00:38:24 2008 +0100
@@ -1,5 +1,5 @@
 
-from django.test import TestCase
+from django.test import TestCase, TransactionTestCase
 from django.contrib.auth.models import User, Permission
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.admin.models import LogEntry
@@ -15,7 +15,7 @@
     ct = ContentType.objects.get_for_model(Model)
     return Permission.objects.get(content_type=ct,codename=perm)
 
-class AdminViewPermissionsTest(TestCase):
+class AdminViewPermissionsTest(TransactionTestCase):
     """Tests for Admin Views Permissions."""
     
     fixtures = ['admin-views-users.xml']
diff -r ed4d2e6277b2 tests/regressiontests/test_client_regress/models.py
--- a/tests/regressiontests/test_client_regress/models.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/tests/regressiontests/test_client_regress/models.py	Fri Aug 08 00:38:24 2008 +0100
@@ -2,7 +2,7 @@
 Regression tests for the Test Client, especially the customized assertions.
 """
 
-from django.test import Client, TestCase
+from django.test import Client, TestCase, TransactionTestCase
 from django.core.urlresolvers import reverse
 from django.core.exceptions import SuspiciousOperation
 
@@ -239,7 +239,7 @@
         except AssertionError, e:
             self.assertEqual(str(e), "The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )")
 
-class LoginTests(TestCase):
+class LoginTests(TransactionTestCase):
     fixtures = ['testdata']
 
     def test_login_different_client(self):
@@ -283,7 +283,7 @@
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.content, 'Hi, Arthur')
 
-class ExceptionTests(TestCase):
+class ExceptionTests(TransactionTestCase):
     fixtures = ['testdata.json']
 
     def test_exception_cleared(self):
diff -r ed4d2e6277b2 tests/regressiontests/views/tests/defaults.py
--- a/tests/regressiontests/views/tests/defaults.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/tests/regressiontests/views/tests/defaults.py	Fri Aug 08 00:38:24 2008 +0100
@@ -1,12 +1,12 @@
 from os import path
 
 from django.conf import settings
-from django.test import TestCase
+from django.test import TransactionTestCase
 from django.contrib.contenttypes.models import ContentType
 
 from regressiontests.views.models import Author, Article
 
-class DefaultsTests(TestCase):
+class DefaultsTests(TransactionTestCase):
     """Test django views in django/views/defaults.py"""
     fixtures = ['testdata.json']
 
diff -r ed4d2e6277b2 tests/regressiontests/views/tests/generic/create_update.py
--- a/tests/regressiontests/views/tests/generic/create_update.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/tests/regressiontests/views/tests/generic/create_update.py	Fri Aug 08 00:38:24 2008 +0100
@@ -1,10 +1,10 @@
 import datetime
 
-from django.test import TestCase
+from django.test import TransactionTestCase
 from django.core.exceptions import ImproperlyConfigured
 from regressiontests.views.models import Article, UrlArticle
 
-class CreateObjectTest(TestCase):
+class CreateObjectTest(TransactionTestCase):
 
     fixtures = ['testdata.json']
 
@@ -65,7 +65,7 @@
             '/views/create_update/view/article/some-other-slug/',
             target_status_code=404)
 
-class UpdateDeleteObjectTest(TestCase):
+class UpdateDeleteObjectTest(TransactionTestCase):
 
     fixtures = ['testdata.json']
 
@@ -111,7 +111,7 @@
         else:
             self.fail('Object was not deleted.')
 
-class PostSaveRedirectTests(TestCase):
+class PostSaveRedirectTests(TransactionTestCase):
     """
     Verifies that the views redirect to the correct locations depending on
     if a post_save_redirect was passed and a get_absolute_url method exists
diff -r ed4d2e6277b2 tests/regressiontests/views/tests/i18n.py
--- a/tests/regressiontests/views/tests/i18n.py	Thu Aug 07 22:23:54 2008 +0100
+++ b/tests/regressiontests/views/tests/i18n.py	Fri Aug 08 00:38:24 2008 +0100
@@ -2,12 +2,12 @@
 import gettext
 
 from django.conf import settings
-from django.test import TestCase
+from django.test import TransactionTestCase
 from django.utils.translation import activate
 
 from regressiontests.views.urls import locale_dir
 
-class I18NTests(TestCase):
+class I18NTests(TransactionTestCase):
     """ Tests django views in django/views/i18n.py """
 
     def test_setlang(self):
