Providing inline "force_login" if "user" keyword argument provided to TestClient.<method> calls (or TestClient.generic)

43 views
Skip to first unread message

Pavel Savchenko

unread,
Apr 22, 2020, 6:48:49 AM4/22/20
to Django developers (Contributions to Django itself)
Hi all,

As a long time Django user, I often found the requirement to use login or force_login somewhat cumbersome.

In comparison, pylons' WebTest has a user keyword argument e.g in their get method, which does that authentication inline.

I am suggesting we make a call to login or force_login if a related argument is passed. Something akin to this:

diff --git a/django/test/client.py b/django/test/client.py
index c460832461..b0a3f89c60 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -726,8 +726,10 @@ class Client(ClientMixin, RequestFactory):
             self.cookies.update(response.cookies)
         return response
 
-    def get(self, path, data=None, follow=False, secure=False, **extra):
+    def get(self, path, data=None, follow=False, secure=False, user=None, **extra):
         """Request a response from the server using GET."""
+        if user:
+            self.force_login(user)
         self.extra = extra
         response = super().get(path, data=data, secure=secure, **extra)
         if follow:

I would love to discuss this suggestion with the rest of you, hopeful to get some more ideas or an agreement or sorts.

And later, if this is agreed to be useful to the community, I could work on the PR.

Kind Regards,
Pavel

Adam Johnson

unread,
Apr 22, 2020, 10:46:29 AM4/22/20
to django-d...@googlegroups.com
Hi Pavel

I think this is a reasonable suggestion to allow tests to be written quickly. It should be noted django-webtest supports this argument already.

I'm not sure it's as simple as a force_login before the request though.

Take these tests:

self.client.force_login(normal_user)
response1 = self.client.get('/home/')
# assert book not visible to "normal user" even though it would be visible to admins
self.client.post('/make-book-visible/1/', user=admin_user)
response2 = self.client.get('/home/')
# assert book now visible to "normal user"

I'd argue it's a reasonable reading that the second get() of /home/ should use normal_user, rather than be left as admin_user after the post().

I think perhaps making `force_login` a context manager, that reverts login state (and cookies) on __exit__, and using that inside the Client's request-making method could work. Not sure how feasible that is though.

Thanks,

Adam

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/d5185a29-4ded-4966-87b3-1149c970eec5%40googlegroups.com.


--
Adam
Reply all
Reply to author
Forward
0 new messages