如何使用Request的多部分表单数据POST解决此AttributeError?

时间:2016-12-26 04:23:48

标签: python python-2.7 python-requests

我正在尝试将文件发布到我的graphql端点@ scaphold.io。我通常会写Javascript,但我必须将此特定操作转换为Python

使用curl执行此操作的命令如下所示(from their docs):

curl -v https://us-west-2.api.scaphold.io/graphql/scaphold-graphql \
  -H "Content-Type:multipart/form-data" \
  -F 'query=mutation CreateFile($input: CreateFileInput!) { createFile(input: $input) { changedFile { id name blobMimeType blobUrl user { id username } } } }' \
  -F 'variables={ "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } };type=application/json' \
  -F myBlobField=@mark-zuckerberg.jpg

blobFieldName中的variables道具与保存要上传文件的Form字段名称相匹配。

使用Requests,我已经走到了这一步:

import requests
from requests_toolbelt import MultipartEncoder

url = 'https://us-west-2.api.scaphold.io/graphql/scaphold-graphql'
multipart_data = MultipartEncoder(
    fields={
        "query":"mutation CreateFile($input: CreateFileInput!) { createFile(input: $input) { changedFile { id name blobMimeType blobUrl user { id username } } } }",
        "variables": { "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } },
        "type":'application/json',
        "myBlobField": ('example.jpg', open('example.jpg', 'rb'), 'image/jpeg' )
        }      
)
req_headers = {'Content-Type':multipart_data.content_type, 'Authorization':'Bearer myreallylongkey'}

r = requests.post(url, data=multipart_data, headers=req_headers)

不幸的是,AttributeError

符合此要求
Traceback (most recent call last):
  File "test-gql.py", line 38, in <module>
    "myBlobField": ('example.jpg', open('example.jpg', 'rb'), 'image/jpeg' )
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 119, in __init__
    self._prepare_parts()
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 240, in _prepare_parts
    self.parts = [Part.from_field(f, enc) for f in self._iter_fields()]
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 488, in from_field
    body = coerce_data(field.data, encoding)
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 466, in coerce_data
    return CustomBytesIO(data, encoding)
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 529, in __init__
    buffer = encode_with(buffer, encoding)
  File "/home/bmp/code/wayhome/python-phash/requests_toolbelt/multipart/encoder.py", line 410, in encode_with
    return string.encode(encoding)
AttributeError: 'dict' object has no attribute 'encode'

我担心我不是Pythonic足以克服这个错误,但我已经消除了一些嫌疑人:

  • querycurl翻译为Python的工作正常,所以我知道这不是权限等。
  • 使用plain/text风格的其他文件,失败并出现相同的错误
  • dictas described here)使用元组元组而不是fields无效

1 个答案:

答案 0 :(得分:3)

从你的例子来看,似乎你正在传递&#34;变量&#34;作为字典,但它应该是一个字符串。变化

        "variables": { "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } },

        "variables": '{ "input": { "name": "Profile Picture", "userId": "VXNlcjoxMA==", "blobFieldName": "myBlobField" } }',

请注意使用单引号使其成为字符串 编辑::从MultipartEncoder的代码,MultipartEncoder尝试在值上运行.encode(...)方法。 .encode(...)附带字符串。因为key&#34;变量&#34;的值的数据类型;是dict,.encode(...)似乎失败了。