Opened 15 years ago
Closed 2 years ago
#14611 closed New feature (fixed)
Added dedicated option to test.Client methods (other than get()) for passing query parameters.
| Reported by: | Jari Pennanen | Owned by: | Tom Carrick |
|---|---|---|---|
| Component: | Testing framework | Version: | 1.2 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I have a view that takes GET and POST parameters, currently there exists django.test.Client.post() and Client.get() but they don't provide means to test this combination cleanly.
As an example solution I suggest to implement Client.request() also which would take POST and GET parameters, e.g.
c = Client()
c.request(reverse('my-view-name'),
get={'getvar' : 'value'},
post={'postvar' : 'value'}, ...)
Currently workaround is to fake this using the post method like this:
c = Client()
c.post(reverse('my-test-view') + '?' + django.utils.http.urlencode({'getvar' : 'value'}),
{'postvar' : 'value'}, ...)
Which as said, is not very clean.
Change History (16)
comment:1 by , 15 years ago
| Owner: | changed from to |
|---|
comment:2 by , 15 years ago
| Needs documentation: | set |
|---|---|
| Needs tests: | set |
| Owner: | changed from to |
| Triage Stage: | Unreviewed → Accepted |
comment:3 by , 15 years ago
Yes you are totally right.
Though I suggest for backwards compatibility to put the getdata as at least third kwarg, if not last, since people probably use the Client.post without specifying the kwarg name, like:
c = Client()
c.post(reverse('my-view-name'], {'postvar': 'value'}, ...)
comment:4 by , 14 years ago
| Severity: | → Normal |
|---|---|
| Type: | → New feature |
comment:5 by , 14 years ago
| Easy pickings: | unset |
|---|---|
| Resolution: | → wontfix |
| Status: | new → closed |
| UI/UX: | unset |
To be honest, the title of this ticket doesn't make much sense given how HTTP works. There are two orthogonal mechanisms involved here:
- 1) HTTP methods
Client.getperforms a GET request;Client.postperforms a POST request.
- 2) HTML forms
- when submitted with a GET, form data is encoded in the query string, and Django exposes it in
request.GET; - when submitted with a POST, it's in the request body, and Django exposes it in
request.POST.
- when submitted with a GET, form data is encoded in the query string, and Django exposes it in
The data argument of the test client is designed to hold simulated form data, and is automatically inserted in requests according to these rules.
That said, it's absolutely legal to use query string parameters in the URL of a POST request. But that isn't be form data. Adding an argument called get_data would be extremely confusing.
In addition, I'm not eager to add a query_string_parameters argument to the test client, because Django favors clean URL design. I'm also afraid of possible confusions with form data in GET requests.
So, for all these reasons, I'm going to reject this ticket. The recommended solution is to use self.client.post('/my/url/?param=value', form_data).
follow-up: 7 comment:6 by , 2 years ago
Would it be possible to reopen and reevaluate this ticket? It’s 11 years later, and I feel this would be a great, simple addition to Django’s testing toolset.
follow-up: 8 comment:7 by , 2 years ago
Replying to Dan Strokirk:
Would it be possible to reopen and reevaluate this ticket? It’s 11 years later, and I feel this would be a great, simple addition to Django’s testing toolset.
For now, I don't see a consensus in the discussion and we need it to reopen the ticket. I'd wait a little longer and get more opinions.
follow-up: 9 comment:8 by , 2 years ago
Replying to Mariusz Felisiak:
Replying to Dan Strokirk:
Would it be possible to reopen and reevaluate this ticket? It’s 11 years later, and I feel this would be a great, simple addition to Django’s testing toolset.
For now, I don't see a consensus in the discussion and we need it to reopen the ticket. I'd wait a little longer and get more opinions.
I think we have consensus in the linked thread and should reopen.
comment:9 by , 2 years ago
| Summary: | django.test.Client is missing post *and* get possibility → Added dedicated option to test.Client methods (other than get()) for passing query parameters. |
|---|
Replying to Lily Foote:
I think we have consensus in the linked thread and should reopen.
Thread discuss adding a dedicated keyword-argument, but I don't see any concrete proposition. How would you like to call it to avoid confusion? query_params maybe.
comment:10 by , 2 years ago
The forum discussion suggested that query_params is the most consistent with similar apis in Django. I'd go with that.
comment:11 by , 2 years ago
| Needs documentation: | unset |
|---|---|
| Needs tests: | unset |
| Resolution: | wontfix |
| Status: | closed → new |
Accepted based on the forum discussion.
comment:12 by , 2 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:14 by , 2 years ago
| Patch needs improvement: | set |
|---|
We need to decide what to do with get() and head().
comment:15 by , 2 years ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
I dislike the
TestClient.requestmethod, because it hides which actual HTTP method is used. The only way to do an HTTP POST should beTestClient.postto avoid ambiguity.However I think that this would work pretty well:
c = Client() c.post(reverse('my-view-name'), getdata={'getvar' : 'value'}, data={'postvar' : 'value'}, ...)i.e., adding a getdata kwarg to the
postmethod. This is useful and doesn't break compatibility, and we still keep a single obvious way to do POST requests.