Code

Ticket #15179: 15179.diff

File 15179.diff, 2.3 KB (added by SmileyChris, 3 years ago)

My take on a completely backwards compatible method

Line 
1diff --git a/django/test/client.py b/django/test/client.py
2index 5cbc0ca..b3bc5c7 100644
3--- a/django/test/client.py
4+++ b/django/test/client.py
5@@ -494,21 +494,44 @@ class Client(RequestFactory):
6             response = self._handle_redirects(response, **extra)
7         return response
8 
9-    def login(self, **credentials):
10+    def login(self, *args, **credentials):
11         """
12-        Sets the Factory to appear as if it has successfully logged into a site.
13+        Sets the Factory to appear as if it has successfully logged into a
14+        site.
15 
16         Returns True if login is possible; False if the provided credentials
17         are incorrect, or the user is inactive, or if the sessions framework is
18         not available.
19+
20+        If the login requires the request used to log in to be passed through
21+        the middleware layers, pass an empty dictionary as a positional
22+        argument::
23+
24+            client.login({}, username='joe', password='password')
25+
26+        This dictionary can contain request metadata required for the
27+        authentication request to succeed, for example::
28+
29+            request_data = {'HTTP_HOST': 'localhost'}
30+            client.login(request_data, username='joe', password='password')
31         """
32+        if args and (len(args) != 1 or not isinstance(args[0], dict)):
33+            raise AttributeError('The login method only accepts a single '
34+                'positional argument which should be a dictionary.')
35         user = authenticate(**credentials)
36         if user and user.is_active \
37                 and 'django.contrib.sessions' in settings.INSTALLED_APPS:
38             engine = import_module(settings.SESSION_ENGINE)
39 
40             # Create a fake request to store login details.
41-            request = HttpRequest()
42+            if args:
43+                # If any request data is provided (even an empty dictionary),
44+                # get a proper request which has passed through the middleware
45+                # layers. The `/login/` URL is simply a dummy location for the
46+                # request.
47+                request = RequestFactory(**args[0]).post("/login/")
48+            else:
49+                request = HttpRequest()
50             if self.session:
51                 request.session = self.session
52             else: