Opened 6 years ago

Closed 5 years ago

#14611 closed New feature (wontfix)

django.test.Client is missing post *and* get possibility

Reported by: Jari Pennanen Owned by: nobody
Component: Testing framework Version: 1.2
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: yes
Needs tests: yes 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 (5)

comment:1 Changed 6 years ago by dmoisset

Needs documentation: unset
Needs tests: unset
Owner: changed from nobody to dmoisset
Patch needs improvement: unset

comment:2 Changed 6 years ago by dmoisset

Needs documentation: set
Needs tests: set
Owner: changed from dmoisset to nobody
Triage Stage: UnreviewedAccepted

I dislike the TestClient.request method, because it hides which actual HTTP method is used. The only way to do an HTTP POST should be TestClient.post to 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 post method. This is useful and doesn't break compatibility, and we still keep a single obvious way to do POST requests.

comment:3 Changed 6 years ago by Jari Pennanen

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 Changed 5 years ago by Julien Phalip

Severity: Normal
Type: New feature

comment:5 Changed 5 years ago by Aymeric Augustin

Easy pickings: unset
Resolution: wontfix
Status: newclosed
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.get performs a GET request;
    • Client.post performs 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.

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).

Note: See TracTickets for help on using tickets.
Back to Top