Vas*_*dis 5 python multipartform-data flask
我创建了一个Flask应用,并想要对其进行测试。在单个端点中,我想发布一个多部分请求,其中包括一个文件和一个复杂的JSON对象。我首先考虑将werkzeug EnvironBuilder用于此任务,因为它似乎提供了一种非常自动化的方法,可以处理内容类型等。准备请求的代码段如下:
# client is an instance of FlaskClient produced using a pytest fixture and the method test client
def _post(endpoint, file_path=None, serialized_message=None):
with open(file_path, 'rb') as fin:
fil = io.BytesIO(fin.read())
file_name = file_path.split(os.sep)[-1]
builder = EnvironBuilder(path='/' + endpoint,
method='POST',
data=json.loads(
serialized_message),
content_type="application/json")
builder.files[file_name] = fil
result = client.open(builder, buffered=True)
return result
Run Code Online (Sandbox Code Playgroud)
失败并显示以下错误:
def _add_file_from_data(self, key, value):
"""Called in the EnvironBuilder to add files from the data dict."""
if isinstance(value, tuple):
self.files.add_file(key, *value)
elif isinstance(value, dict):
from warnings import warn
warn(DeprecationWarning('it\'s no longer possible to pass dicts '
'as `data`. Use tuples or FileStorage '
'objects instead'), stacklevel=2)
value = dict(value)
mimetype = value.pop('mimetype', None)
if mimetype is not None:
value['content_type'] = mimetype
> self.files.add_file(key, **value)
E TypeError: add_file() got an unexpected keyword argument 'globalServiceOptionId'
Run Code Online (Sandbox Code Playgroud)
随着globalServiceOptionId是在我张贴的字典中的嵌套字典的关键。我有一些绕过这个问题的想法,可以将内部字典转换为jsons字符串,但是我希望得到更具体的答案,因为我不希望在测试内部和外部更改请求的表示形式。谢谢。
密码字典的形式并不重要,只要它内部嵌套了字典即可。在此示例中给出了此json:
{
"attachments": [],
"Ids": [],
"globalServiceOptions": [{
"globalServiceOptionId": {
"id": 2,
"agentServiceId": {
"id": 2
},
"serviceOptionName": "Time",
"value": "T_last",
"required": false,
"defaultValue": "T_last",
"description": "UTC Timestamp",
"serviceOptionType": "TIME"
},
"name": "Time",
"value": null
}]
}
Run Code Online (Sandbox Code Playgroud)
我测试了另一个代码段:
def _post(endpoint, file_path=None, serialized_message=None):
with open(file_path, 'rb') as fin:
fil = io.BytesIO(fin.read())
files = {
'file': (file_path, fil, 'application/octet-stream')
}
for key, item in json.loads(serialized_message).items():
files[key] = (None, json.dumps(item), 'application/json')
builder = EnvironBuilder(path='/' + endpoint,
method='POST', data=files,
)
result = client.open(builder, buffered=True)
return result
Run Code Online (Sandbox Code Playgroud)
尽管运行时没有错误,但Flask将(按预期)将传入的json识别为文件,这再次需要在测试和正常运行期间进行不同的处理。
我遇到了类似的问题,最终对我有用的是更改数据方法以排除嵌套字典。获取示例 JSON,执行以下操作应该可以清除EnvironBuilder:
data_json = {
"attachments": [],
"Ids": [],
"globalServiceOptions": [json.dumps({ # Dump all nested JSON to a string representation
"globalServiceOptionId": {
"id": 2,
"agentServiceId": {
"id": 2
},
"serviceOptionName": "Time",
"value": "T_last",
"required": false,
"defaultValue": "T_last",
"description": "UTC Timestamp",
"serviceOptionType": "TIME"
},
"name": "Time",
"value": null
})
]
}
builder = EnvironBuilder(path='/' + endpoint,
method='POST',
data=data_json,
content_type="application/json")
Run Code Online (Sandbox Code Playgroud)
采用上述方法仍然允许正确传递嵌套的 dict/JSON,同时清除 werkzeug 限制。
| 归档时间: |
|
| 查看次数: |
538 次 |
| 最近记录: |