diff --git a/django/test/client.py b/django/test/client.py
index 08e3ff6..41e0db5 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -179,6 +179,7 @@ class Client(object):
         self.cookies = SimpleCookie()
         self.exc_info = None
         self.errors = StringIO()
+        self._session_store = None
 
     def store_exc_info(self, **kwargs):
         """
@@ -188,16 +189,38 @@ class Client(object):
 
     def _session(self):
         """
-        Obtains the current session variables.
+        Obtains a SessionStore containing all the current session variables.
         """
-        if 'django.contrib.sessions' in settings.INSTALLED_APPS:
-            engine = import_module(settings.SESSION_ENGINE)
-            cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
-            if cookie:
-                return engine.SessionStore(cookie.value)
-        return {}
+        if self._session_store == None:
+            if 'django.contrib.sessions' in settings.INSTALLED_APPS:
+                cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
+                engine = import_module(settings.SESSION_ENGINE)
+                if cookie:
+                    self._session_store = engine.SessionStore(cookie.value)
+                else:
+                    self._session_store = engine.SessionStore()
+                    # if load() fails the cookie changes, so save() first
+                    self._session_store.save()  
+                    self.cookies[settings.SESSION_COOKIE_NAME] = \
+                         self._session_store.session_key
+            else:
+                self._session_store = {}
+        return self._session_store
     session = property(_session)
 
+    def _session_save(self):
+        """
+        Push the session store to the database then set the current
+        session to None so that it is reloaded on subsquent requests.
+        """
+        if hasattr(self._session_store, 'modified'):
+            if self._session_store.modified:
+                self._session_store.save()
+                # update the cookie in case cycle_key() was called
+                self.cookies[settings.SESSION_COOKIE_NAME] = \
+                     self._session_store.session_key
+            self._session_store = None
+
     def request(self, **request):
         """
         The master request method. Composes the environment dictionary
@@ -285,6 +308,7 @@ class Client(object):
         """
         Requests a response from the server using GET.
         """
+        self._session_save()
         parsed = urlparse(path)
         r = {
             'CONTENT_TYPE':    'text/html; charset=utf-8',
@@ -305,6 +329,7 @@ class Client(object):
         """
         Requests a response from the server using POST.
         """
+        self._session_save()
         if content_type is MULTIPART_CONTENT:
             post_data = encode_multipart(BOUNDARY, data)
         else:
@@ -336,6 +361,7 @@ class Client(object):
         """
         Request a response from the server using HEAD.
         """
+        self._session_save()
         parsed = urlparse(path)
         r = {
             'CONTENT_TYPE':    'text/html; charset=utf-8',
@@ -355,6 +381,7 @@ class Client(object):
         """
         Request a response from the server using OPTIONS.
         """
+        self._session_save()
         parsed = urlparse(path)
         r = {
             'PATH_INFO':       urllib.unquote(parsed[2]),
@@ -374,6 +401,7 @@ class Client(object):
         """
         Send a resource to the server using PUT.
         """
+        self._session_save()
         if content_type is MULTIPART_CONTENT:
             post_data = encode_multipart(BOUNDARY, data)
         else:
@@ -405,6 +433,7 @@ class Client(object):
         """
         Send a DELETE request to the server.
         """
+        self._session_save()
         parsed = urlparse(path)
         r = {
             'PATH_INFO':       urllib.unquote(parsed[2]),
@@ -430,31 +459,12 @@ class Client(object):
         user = authenticate(**credentials)
         if user and user.is_active \
                 and 'django.contrib.sessions' in settings.INSTALLED_APPS:
-            engine = import_module(settings.SESSION_ENGINE)
 
             # Create a fake request to store login details.
             request = HttpRequest()
-            if self.session:
-                request.session = self.session
-            else:
-                request.session = engine.SessionStore()
+            request.session = self.session
             login(request, user)
 
-            # Save the session values.
-            request.session.save()
-
-            # Set the cookie to represent the session.
-            session_cookie = settings.SESSION_COOKIE_NAME
-            self.cookies[session_cookie] = request.session.session_key
-            cookie_data = {
-                'max-age': None,
-                'path': '/',
-                'domain': settings.SESSION_COOKIE_DOMAIN,
-                'secure': settings.SESSION_COOKIE_SECURE or None,
-                'expires': None,
-            }
-            self.cookies[session_cookie].update(cookie_data)
-
             return True
         else:
             return False
@@ -465,6 +475,7 @@ class Client(object):
 
         Causes the authenticated user to be logged out.
         """
+        self._session_store = None
         session = import_module(settings.SESSION_ENGINE).SessionStore()
         session_cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
         if session_cookie:
diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py
index 22b59e5..9bd9134 100644
--- a/tests/regressiontests/test_client_regress/models.py
+++ b/tests/regressiontests/test_client_regress/models.py
@@ -677,6 +677,33 @@ class SessionTests(TestCase):
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.content, 'YES')
 
+    def test_session_manipulation(self):
+        # Check that the existing documented behavior works
+        session = self.client.session
+        session["session_var"] = "foo"
+        session.save()
+
+        response = self.client.get('/test_client_regress/check_session/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.content, 'foo')
+
+    def test_direct_session_manipulation(self):
+        self.client.session['session_var'] = 'bar'
+
+        # Check that the session has been modified
+        response = self.client.get('/test_client_regress/check_session/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.content, 'bar')
+
+        # Check that the session variable persists over login
+        # when cycle_key() is called
+        login = self.client.login(username='testclient', password='password')
+        response = self.client.get('/test_client_regress/check_session/')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.content, 'bar')
+
+        self.assertEqual(self.client.session.pop('session_var'), 'bar')
+
     def test_logout(self):
         """Logout should work whether the user is logged in or not (#9978)."""
         self.client.logout()
