2016-12-26 113 views
0

我正在嘗試將文件發佈到我的graphql endpoint @ scaphold.io。我通常寫Javascript,但我必須將這個特定操作轉換爲Python如何使用請求的多部分表單數據POST解決此AttributeError?

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 [email protected] 

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' 

我怕我不夠Python的神交此錯誤,但我已經消除了一些嫌疑人:

  • 翻譯簡單querycurlPython正常工作,所以我知道這是不是權限等
  • 使用不同的文件,對plain/text味,失敗瓦特/同樣的錯誤
  • 使用元組的元組,而不是對於fields一個dictas described here)沒有任何影響
+0

curl轉換器:http://curl.trillworks.com/和https://shibukawa.github.io/curl_as_dsl/index.html – furas

+2

看到你的最後一個鏈接 - 它們使用'files ='的元組,而不是' data =' – furas

+0

@furas謝謝,這些轉換器很棒(尤其是第一個)。只需要注意其他人是否嘗試使用它們:第二個轉換器僅支持python 3,並且第一個轉換器似乎錯誤地截斷了帶有「=」字符的任何字符串。否則,其代碼看起來是正確的。 re:'files' vs'data',我相信在使用'MultpartEncoder'時,參數會變成'data'。至少,在接受答案中實施解決方案時,我可以說「數據」起作用。 – Brandon

回答

2

從你的榜樣,它似乎要傳遞「變量」作爲一本字典,而是它應該是一個字符串。更改

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

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

請注意使用單引號,使之成爲字符串 編輯::從MultipartEncoder的代碼,MultipartEncoder嘗試運行.encode(...)方法在價值觀上。 .encode(...)帶有字符串。由於鍵「變量」的值的數據類型是字典,.encode(...)似乎失敗了。

相關問題