flask restplus Request Parsing-请求解析

Flask-RESTPlus 的请求解析接口 ,reqparse是根据该接口建模的argparse。它旨在提供对 flask.requestFlask 中对象上的任何变量的简单且统一的访问。

基本参数

这是请求解析器的一个简单示例。它在flask.Request.values字典中查找两个参数:一个整数和一个字符串

1
2
3
4
5
6
from flask_restplus import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate cannot be converted')
parser.add_argument('name', required=True, help="Name cannot be blank!")
args = parser.parse_args()
  • 默认参数类型是 unicode 字符串。这将str在 python3 和unicodepython2 中。

  • 如果指定该help值,则在解析时引发类型错误时,它将呈现为错误消息。如果未指定帮助消息,则默认行为是从类型错误本身返回消息。

  • required=True:表示此参数为必须

未在 RequestParser 中声明的参数将被忽略。

在请求解析器中声明但未在请求本身中设置的参数将默认为None.

多个值和列表

如果您想接受一个键的多个值作为列表,您可以通过action='append'

1
parser.add_argument('name', action='append')

这将让您进行如下查询

1
curl http://api.example.com -d "name=bob" -d "name=sue" -d "name=joe"

你的 args 看起来像这样:

1
2
args = parser.parse_args()
args['name'] # ['bob', 'sue', 'joe']

如果您希望使用逗号分隔列表,请使用action='split'

1
parser.add_argument('fruits', action='split')

这将让您进行如下查询

1
curl http://api.example.com -d "fruits=apple,lemon,cherry"

你的 args 看起来像这样:

1
2
args = parser.parse_args()
args['fruits'] # ['apple', 'lemon', 'cherry']

其他目的地

如果由于某种原因您希望参数在解析后以不同的名称存储,您可以使用dest关键字参数。

1
2
3
4
parser.add_argument('name', dest='public_name')

args = parser.parse_args()
args['public_name']

参数位置

默认情况下,RequestParser 尝试解析来自 flask.Request.values和的值flask.Request.json

使用location参数来 add_argument() 指定从中提取值的备用位置上的任何变量flask.Request都可以使用。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Look only in the POST body
parser.add_argument('name', type=int, location='form')

# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')

# From the request headers
parser.add_argument('User-Agent', location='headers')

# From http cookies
parser.add_argument('session_id', location='cookies')

# From file uploads
parser.add_argument('picture', type=werkzeug.datastructures.FileStorage, location='files')

笔记

type=list 时使用location='json'

笔记

使用location='form'是验证表单数据和记录表单字段的方法。

多个位置

可以通过将列表传递给来指定多个参数位置location

1
parser.add_argument('text', location=['headers', 'values'])

当指定多个位置时,来自所有指定位置的参数将组合成一个MultiDict. 最后location列出的优先于结果集中。

如果参数位置列表包括headers 位置,则参数名称将不再区分大小写,并且必须匹配它们的标题大小写名称(请参阅 参考资料str.title())。指定 location='headers'(不是列表)将保持不区分大小写。

高级类型处理

有时,您需要的不仅仅是原始类型来处理输入验证。该inputs模块提供了一些常见的类型处理,例如:

您只需将它们用作类型参数:

1
parser.add_argument('flag', type=inputs.boolean)

有关可用输入的完整列表,请参阅inputs文档。

你也可以自己写:

1
2
3
4
5
6
7
8
def my_type(value):
'''Parse my type'''
if not condition:
raise ValueError('This is not my type')
return parse(value)

# Swagger documntation
my_type.__schema__ = {'type': 'string', 'format': 'my-custom-format'}

解析器继承

通常你会为你编写的每个资源创建一个不同的解析器。问题在于解析器是否有共同的论点。您可以编写一个包含所有共享参数的父解析器,而不是重写参数,然后使用copy(). 您还可以使用 覆盖父项中的任何参数 replace_argument(),或使用 将其完全删除remove_argument()。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask_restplus import reqparse

parser = reqparse.RequestParser()
parser.add_argument('foo', type=int)

parser_copy = parser.copy()
parser_copy.add_argument('bar', type=int)

# parser_copy has both 'foo' and 'bar'

parser_copy.replace_argument('foo', required=True, location='json')
# 'foo' is now a required str located in json, not an int as defined
# by original parser

parser_copy.remove_argument('foo')
# parser_copy no longer has 'foo' argument

文件上传

要使用 处理文件上传RequestParser,您需要使用文件位置并将类型设置为FileStorage.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from werkzeug.datastructures import FileStorage

upload_parser = api.parser()
upload_parser.add_argument('file', location='files',
type=FileStorage, required=True)


@api.route('/upload/')
@api.expect(upload_parser)
class Upload(Resource):
def post(self):
uploaded_file = args['file'] # This is FileStorage instance
url = do_something_with_file(uploaded_file)
return {'url': url}, 201

请参阅专门的 Flask 文档部分

错误处理

RequestParser 处理错误的默认方式是在发生第一个错误时中止。当您有可能需要一些时间来处理的论点时,这可能会很有用。但是,通常最好将错误捆绑在一起并一次性发送回客户端。可以在 Flask 应用程序级别或特定的 RequestParser 实例上指定此行为。要使用捆绑错误选项调用 RequestParser,请传入参数bundle_errors。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from flask_restplus import reqparse

parser = reqparse.RequestParser(bundle_errors=True)
parser.add_argument('foo', type=int, required=True)
parser.add_argument('bar', type=int, required=True)

# If a request comes in not containing both 'foo' and 'bar', the error that
# will come back will look something like this.

{
"message": {
"foo": "foo error message",
"bar": "bar error message"
}
}

# The default behavior would only return the first error

parser = RequestParser()
parser.add_argument('foo', type=int, required=True)
parser.add_argument('bar', type=int, required=True)

{
"message": {
"foo": "foo error message"
}
}

应用程序配置键是“BUNDLE_ERRORS”。例如

1
2
3
4
from flask import Flask

app = Flask(__name__)
app.config['BUNDLE_ERRORS'] = True

警告

BUNDLE_ERRORS是覆盖bundle_errors 单个RequestParser实例中的选项的全局设置。

错误信息

每个字段的错误消息可以使用help参数 to Argument(以及RequestParser.add_argument)进行自定义。

如果未提供帮助参数,则该字段的错误消息将是类型错误本身的字符串表示形式。如果help提供,则错误消息将是 的值help

help可能包含一个插值标记 ,{error_msg}它将被替换为类型错误的字符串表示形式。这允许在保留原始错误的同时自定义消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from flask_restplus import reqparse


parser = reqparse.RequestParser()
parser.add_argument(
'foo',
choices=('one', 'two'),
help='Bad choice: {error_msg}'
)

# If a request comes in with a value of "three" for `foo`:

{
"message": {
"foo": "Bad choice: three is not a valid choice",
}
}

flask restplus Request Parsing-请求解析
https://flepeng.github.io/021-Python-32-框架-Flask-flask-restplus-flask-restplus-Request-Parsing-请求解析/
作者
Lepeng
发布于
2021年3月31日
许可协议