Try urllib.parse.urlencode:
>>> from urllib.parse import urlencode
>>> urlencode({'foo': 1, 'bar': 2})
'foo=1&bar=2'
Answer from Frank Fang on Stack OverflowTry urllib.parse.urlencode:
>>> from urllib.parse import urlencode
>>> urlencode({'foo': 1, 'bar': 2})
'foo=1&bar=2'
Simply iterte over the items, join the key and value and create a key/value pair separated by '=' and finally join the pairs by '&'
For Ex...
If d={'v_1_name':'v_1_value','v_2_name':'v_2_value','v_3_name':'v_3_value'}
Then
'&'.join('='.join([k,v]) for k,v in d.iteritems())
is
'v_2_name=v_2_value&v_1_name=v_1_value&v_3_name=v_3_value'
python - Converting x-www-form-urlencoded query string to a dict - Stack Overflow
web - How to convert python dict to raw url-encoded form data? - Stack Overflow
Converting dictionary to url encoded data for passing application/x-www-form-urlencoded in python - Stack Overflow
Python requests dict as form-data - Stack Overflow
Use urllib.parse.urlencode(). It takes a dictionary of key-value pairs, and converts it into a form suitable for a URL (e.g., key1=val1&key2=val2).
For your example:
>>> import urllib.parse
>>> params = {'a':'A', 'b':'B'}
>>> urllib.parse.urlencode(params)
'a=A&b=B'
If you want to make a URL with repetitive params such as: p=1&p=2&p=3 you have two options:
>>> a = (('p',1),('p',2), ('p', 3))
>>> urllib.parse.urlencode(a)
'p=1&p=2&p=3'
or:
>>> urllib.parse.urlencode({'p': [1, 2, 3]}, doseq=True)
'p=1&p=2&p=3'
If you are still using Python 2, use urllib.urlencode().
For python 3, the urllib library has changed a bit, now you have to do:
from urllib.parse import urlencode
params = {'a':'A', 'b':'B'}
urlencode(params)
The reason you're getting JSON is because you're explicitly calling json.dumps to generate a JSON string. Just don't do that, and you won't get a JSON string. In other words, change your first line to this:
data = {'param1': 'value1', 'param2': 'value2'}
As the docs explain, if you pass a dict as the data value, it will be form-encoded, while if you pass a string, it will be sent as-is.
For example, in one terminal window:
$ nc -kl 8765
In another:
$ python3
>>> import requests
>>> d = {'spam': 20, 'eggs': 3}
>>> requests.post("http://localhost:8765", data=d)
^C
>>> import json
>>> j = json.dumps(d)
>>> requests.post("http://localhost:8765", data=j)
^C
In the first terminal, you'll see that the first request body is this (and Content-Type application/x-www-form-urlencoded):
spam=20&eggs=3
โฆ while the second is this (and has no Content-Type):
{"spam": 20, "eggs": 3}
Short answer with example:
import requests
the_data = {"aaa": 1, "bbb": 2, "ccc": "yeah"}
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
# Execute the post
requests.post("http://bla.bla.example.com", data=the_data, headers=headers)
# You have POSTed this HTTP body: aaa=1&bbb=2&ccc=yeah (note, although the content-type is called urlencoded the data is not in the URL but in the http body)
# to this url: "http://bla.bla.example.com"
Requests library does all the JSON to urlencoded string conversion for you
References:
MDN Web docs, Requests lib post url-encoded form
You don't need to explicitly encode it, simply pass your dict to data argument and it will be encoded automatically.
>>> r = requests.post(URL, data = {'key':'value'})
From the official documentation:
Typically, you want to send some form-encoded data โ much like an HTML form. To do this, simply pass a dictionary to the data argument. Your dictionary of data will automatically be form-encoded when the request is made
Set the Content-Type header to application/x-www-form-urlencoded.
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
r = requests.post(URL, data=params, headers=headers)
OK people. I implemented it myself:
import urllib
def recursive_urlencode(d):
"""URL-encode a multidimensional dictionary.
>>> data = {'a': 'b&c', 'd': {'e': {'f&g': 'h*i'}}, 'j': 'k'}
>>> recursive_urlencode(data)
u'a=b%26c&j=k&d[e][f%26g]=h%2Ai'
"""
def recursion(d, base=[]):
pairs = []
for key, value in d.items():
new_base = base + [key]
if hasattr(value, 'values'):
pairs += recursion(value, new_base)
else:
new_pair = None
if len(new_base) > 1:
first = urllib.quote(new_base.pop(0))
rest = map(lambda x: urllib.quote(x), new_base)
new_pair = "%s[%s]=%s" % (first, ']['.join(rest), urllib.quote(unicode(value)))
else:
new_pair = "%s=%s" % (urllib.quote(unicode(key)), urllib.quote(unicode(value)))
pairs.append(new_pair)
return pairs
return '&'.join(recursion(d))
if __name__ == "__main__":
import doctest
doctest.testmod()
Still, I'd be interested to know if there's a better way to do this. I can't believe Python's standard library doesn't implement this.
Something like this?
a = {'a': 'b', 'c': {'d': 'e'}}
url = urllib.urlencode([('%s[%s]'%(k,v.keys()[0]), v.values()[0] ) if type(v)==dict else (k,v) for k,v in a.iteritems()])
url = 'a=b&c%5Bd%5D=e'
