Using PyQt 5 and Python 2.7, this was a bit of a struggle for me to figure out, despite the helpful answer from Ilya elsewhere on this page.
Here's what finally worked for me (OP's example converted to Python2.7/PyQt5):
url_query = QUrlQuery()
url_query.addQueryItem('test', str(QtCore.QUrl.toPercentEncoding('hello+world')))
manager.post(request, str(url_query.toString(QUrl.FullyEncoded)))
And here's a complete example using httpbin.org to check the posted content:
import sys
import json
from PyQt5 import QtCore, QtWidgets, QtNetwork
def slot_finished(reply):
""" Get form data from reply content """
reply_content = json.loads(str(reply.readAll()))
print 'returned: {}'.format(reply_content['form'][KEY])
# Some variables
url = u'http://httpbin.org/post'
content_type = u'application/x-www-form-urlencoded'
KEY = 'test'
data = u'hello + world'
# Build content for the request
url_query = QtCore.QUrlQuery()
url_query.addQueryItem(KEY, str(QtCore.QUrl.toPercentEncoding(data)))
content = str(url_query.toString(QtCore.QUrl.FullyEncoded))
# Post the request and show the reply content
app = QtWidgets.QApplication(sys.argv)
manager = QtNetwork.QNetworkAccessManager()
manager.finished.connect(slot_finished)
manager.finished.connect(app.quit) # relies on connection order
request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader, content_type)
reply = manager.post(request, content)
print 'expected: {}'.format(data)
app.exec_()
Note: not sure why, but the example also seems to work without explicitly setting QtCore.QUrl.FullyEncoded
. Here's what the Qt docs have to say about that constant:
Leave all characters in their properly-encoded form, as this component
would appear as part of a URL. When used with toString(), this
produces a fully-compliant URL in QString form, exactly equal to the
result of toEncoded()