Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Restore the ability to use a list of 2-tuples for the data keyword argument with requests.post. #1103

Merged
merged 1 commit into from

3 participants

David McKeone Kenneth Reitz Piotr Dobrogost
David McKeone

As of commit ef8563a the ability to pass a keyword argument like data=[('key', 'value'), ('key', 'value2')] was broken because the is_stream detection in PreparedRequest.prepare_body(self, data, files) fails to look for a list of 2-tuples.

Just in case this is deemed to be an unnecessary change (because the calling code could switch to using a dict), Il'l make note here that this is required in order to pass POST parameters where the key is the same, but values are different.

form_data = [('item', 1), ('item', 2), ('item', 3)]
resp = requests.post('http://www.example.com', data=form_data)
Kenneth Reitz

Actually, the proper syntax for that is slightly different.

form_data = {'item': [1, 2, 3]}
resp = requests.post('http://www.example.com', data=form_data)
David McKeone

I see the syntactical niceness of that example for simple cases(thanks for showing it, I didn't realize I could do that), but I'd still like to make my case for the way that it worked previously.

I'm currently using Werkzeug OrderedMultiDict to hold the parameters that eventually make it into the data argument. Some of my uses can have quite a few parameters and, since it's ordered, the order of the parameters does matter in the POST data (working with a legacy system).

WIth a list of 2-tuples I can do: data=ordered_multi_dict_instance.items(multi=true). So the 2-tuple is quite easy to create from a dict-like object that iterates. I may be wrong, but this new syntax deviates in such a way that I'd have to marshall all the data into it and maintain the order at the same time.

I also face an issue with the fact that this legacy system I'm working with requires not just multiple keys but ordered multiple keys. Something like: Item=1&Value=10&OtherValue=100&Item=2&Value=200&OtherValue=200&Item=3&Value=30&OtherValue=300. Presumably, that would result in form_data = {'Item': [1, 2, 3], 'Value': [10, 20, 30], 'OtherValue': [100, 200, 300]} in the new syntax, which would likely re-order the parameters based on the names of Item, Value and OtherValue, and not in the repeating ordered sequence: Item, Value, OtherValue.

Piotr Dobrogost

Related: issue #522

Kenneth Reitz

We need to support MultiDict. This is long overdue.

David McKeone

Accepting MultiDict for the data= keyword would be acceptable for me.

David McKeone

So, moving this forward.

As it stands commit ef8563a is a breaking change from 1.0X to 1.10 for my particular use case. The workaround I have is:

form_data = RequestEncodingMixin._encode_params(request.values.items(multi=True))
resp = requests.post('http://www.example.com', data=form_data)

Is this particular pull request viable as a stop-gap between now and MultiDict support or is passing a 2-tuple list into data= a no-go for the future?

Kenneth Reitz

Merged.

Kenneth Reitz kennethreitz merged commit 9d1d927 into from
David McKeone dmckeone referenced this pull request
Open

Add MultiDict Support #1155

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 16, 2013
  1. Allow passing POST data with a list of 2-tuples.

    David McKeone authored
This page is out of date. Refresh to see the latest.
Showing with 1 addition and 0 deletions.
  1. +1 −0  requests/models.py
1  requests/models.py
View
@@ -342,6 +342,7 @@ def prepare_body(self, data, files):
is_stream = all([
hasattr(data, '__iter__'),
not isinstance(data, basestring),
+ not isinstance(data, list),
not isinstance(data, dict)
])
Something went wrong with that request. Please try again.