Suggestion: Adding `params` to TestClient HTTP methods

Using Client.get it’s very easy to add new query parameters to the fake request, you can simply provide them to data argument. Very nice and ergonomic.

However, for the other HTTP methods, like post, this doesn’t work, since of course they use the same parameter for their form data.

Would it make sense to provide a new params argument to all Client HTTP methods, that would work similar to the requests / httpx libraries?

1 Like

It could! I usually use urlencode to put dynamic parameters in the URL:

resp = self.client.post("/widget/" + urlencode({"user": user.id}))

But this is hard to remember, and can lead to random failures if testing with random data that sometimes needs escaping.

Having a parameter for URL parameters would be neat. I’d suggest we use the name query_params, rather than just params, as per the ongoing Google Summer of Code project that will rename request.GET to request.query_params ( [GSOC 2023] Add Configurable Content Type Parsing and Modernise Request Object ).

2 Likes

It think that makes a lot of sense.

params will probably be most familiar to developers used to requests and similar, and is a little shorter, but internal consistency with Django itself is even better. Makes for good consistency with request.user, which can also be set via Client.

Great. Would you like to make a ticket?

1 Like

Ticket created! #34640 (Add query_params argument to test Client methods) – Django

Seems like this was already requested 11 years ago and closed as wontfix… so technically a duplicate.

As an aside, what’s Django’s policy when it comes to re-assessing old ideas? Do we ever reconsider, or is a wontfix a wontfix?

I think that query parameters should (per REST philosophy) be used only for get requests and it would make little sense to use them in POST/PUT requests, as the data is sent using other means in that case, and adding an extra argument to the test client would unnecessary (imo) complicate it.

Note that Django views can be used for much more than only REST APIs, and in the wild plenty of views take both query parameters and POST data.

A few quick examples:

Although, talking about “REST philosophy”… :thinking: what about the REST pattern says that only GET / DELETE requests should have query parameters? It’s the first time I’ve heard that suggested.

When talking about REST philosophy, I meant this: GET requests are queries, i.e. they query data. The rest of them, like POST, PUT, PATCH, DELETE are mutations, they do not get the data, they modify it on the server. Therefore, query parameters are only meant for GET requests, as they are query parameters

Philosophy or not, there is nothing in the specs forbidding a POST request with body data and query params. I doubt it is often used, but that doesn’t necessarily mean that we should limit our code.

4 Likes

The Django Test Client is not just used for REST, and yes, there are usecases, where GET params get used in APIs even on POST. It is after all allowed, and is e.g. a very nice way for proxies to add s2s data on top, or to make the calls themselves leave obvious traces in the logs, that do not interfere with the underlying POST/PUT functionality.

The main reason however is, that re-using data in .get already seems inconsistent with reality and other frameworks, and it would be much more explicit, to use GET params with another key-word, because it is actually a different type of parameter than the body encoded data.

In my opinion, I would rather use a params keyword of any sort even on client.get() right now, as it is less confusing, and simply more correct.

1 Like