11# Note that we import as `DjangoRequestFactory` and `DjangoClient` in order
22# to make it harder for the user to import the wrong thing without realizing.
33import io
4+ from contextlib import contextmanager
45from importlib import import_module
56
67from django .conf import settings
78from django .core .exceptions import ImproperlyConfigured
89from django .core .handlers .wsgi import WSGIHandler
10+ from django .core .signals import request_finished , request_started
11+ from django .db import close_old_connections
912from django .test import override_settings , testcases
1013from django .test .client import Client as DjangoClient
1114from django .test .client import ClientHandler
@@ -22,6 +25,21 @@ def force_authenticate(request, user=None, token=None):
2225 request ._force_auth_token = token
2326
2427
28+ @contextmanager
29+ def _keep_connections_open ():
30+ """
31+ Prevent Django from closing the database connection while a request
32+ is dispatched, matching the behavior of Django's ClientHandler.
33+ """
34+ request_started .disconnect (close_old_connections )
35+ request_finished .disconnect (close_old_connections )
36+ try :
37+ yield
38+ finally :
39+ request_started .connect (close_old_connections )
40+ request_finished .connect (close_old_connections )
41+
42+
2543if requests is not None :
2644 class HeaderDict (requests .packages .urllib3 ._collections .HTTPHeaderDict ):
2745 def get_all (self , key , default ):
@@ -90,7 +108,8 @@ def start_response(wsgi_status, wsgi_headers, exc_info=None):
90108
91109 # Make the outgoing request via WSGI.
92110 environ = self .get_environ (request )
93- wsgi_response = self .app (environ , start_response )
111+ with _keep_connections_open ():
112+ wsgi_response = self .app (environ , start_response )
94113
95114 # Build the underlying urllib3.HTTPResponse
96115 raw_kwargs ['body' ] = io .BytesIO (b'' .join (wsgi_response ))
0 commit comments