Flask-RESTful

Flask-RESTful是Flask的扩展,增加了对快速构建REST API的支持。 它是一个轻量级的抽象,可与现有的ORM /库一起使用。 Flask-RESTful以最少的设置鼓励最佳实践。 如果你熟悉Flask,Flask-RESTful应该很容易学会。

用户指南

这部分文档将向您展示如何开始在Flask中使用Flask-RESTful。

安装

pip安装Flask-RESTful

pip install flask-restful

开发版本可以从的GitHub下载

git clone https://github.com/flask-restful/flask-restful.git
cd flask-restful
python setup.py develop

Flask-RESTful具有以下依赖关系(如果使用pip,它将自动安装):

  • Flask版本0.8或更高

Flask-RESTful需要Python版本2.6,2.7,3.3,3.4,3.5或3.6。

快速开始

现在是编写您的第一个REST API的时候了。 本指南假设您对Flask有一定的理解,并且您已经安装了Flask和Flask-RESTful。 如果不是,请按照安装部分中的步骤进行操作。

最小的API

最小的Flask-RESTful API如下所示:

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class HelloWorld(Resource):
    def get(self):
        return {'hello': 'world'}

api.add_resource(HelloWorld, '/')

if __name__ == '__main__':
    app.run(debug=True)

将其另存为api.py并使用Python解释器运行它。 请注意,我们已启用Flask调试模式来提供代码重新加载和更好的错误消息。

$ python api.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader

警告

调试模式不应该在生产环境中使用!

现在打开一个新的提示窗口,用curl测试你的API

$ curl http://127.0.0.1:5000/
{"hello": "world"}

资源路由

Flask-RESTful提供的主要构建块是资源。 资源建立在Flask可插入视图之上,只需通过定义资源上的方法,便可轻松访问多个HTTP方法。 一个 todo 应用程序的基本 CRUD资源 (当然)如下所示:

from flask import Flask, request
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

todos = {}

class TodoSimple(Resource):
    def get(self, todo_id):
        return {todo_id: todos[todo_id]}

    def put(self, todo_id):
        todos[todo_id] = request.form['data']
        return {todo_id: todos[todo_id]}

api.add_resource(TodoSimple, '/<string:todo_id>')

if __name__ == '__main__':
    app.run(debug=True)

你可以这样尝试:

$ curl http://localhost:5000/todo1 -d "data=Remember the milk" -X PUT
{"todo1": "Remember the milk"}
$ curl http://localhost:5000/todo1
{"todo1": "Remember the milk"}
$ curl http://localhost:5000/todo2 -d "data=Change my brakepads" -X PUT
{"todo2": "Change my brakepads"}
$ curl http://localhost:5000/todo2
{"todo2": "Change my brakepads"}

如果您安装了requests库,则可以从python测试:

>>> from requests import put, get
>>> put('http://localhost:5000/todo1', data={'data': 'Remember the milk'}).json()
{u'todo1': u'Remember the milk'}
>>> get('http://localhost:5000/todo1').json()
{u'todo1': u'Remember the milk'}
>>> put('http://localhost:5000/todo2', data={'data': 'Change my brakepads'}).json()
{u'todo2': u'Change my brakepads'}
>>> get('http://localhost:5000/todo2').json()
{u'todo2': u'Change my brakepads'}

Flask-RESTful可以理解来自视图方法的多种返回值。 与Flask类似,您可以返回任何可迭代,并将其转换为响应,包括原始Flask响应对象。 Flask-RESTful还支持使用多个返回值设置响应代码和响应头,如下所示:

class Todo1(Resource):
    def get(self):
        # Default to 200 OK
        return {'task': 'Hello world'}

class Todo2(Resource):
    def get(self):
        # Set the response code to 201
        return {'task': 'Hello world'}, 201

class Todo3(Resource):
    def get(self):
        # Set the response code to 201 and return custom headers
        return {'task': 'Hello world'}, 201, {'Etag': 'some-opaque-string'}

端点

很多时候在API中,你的资源将有多个URL。 您可以将多个URL传递给Api对象上的add_resource()方法。 每一个将被路由到您的资源

api.add_resource(HelloWorld,
    '/',
    '/hello')

您也可以将部分路径作为变量与您的资源方法进行匹配。

api.add_resource(Todo,
    '/todo/<int:todo_id>', endpoint='todo_ep')

注意

如果请求与任何应用程序的端点不匹配,Flask-RESTful将返回一个404错误消息,其中包含与请求端点密切匹配的其他端点的建议。 这可以通过在您的应用程序配置中将ERROR_404_HELP设置为False来禁用。

参数解析

虽然Flask可以方便地访问请求数据(即查询字符串或POST表单编码数据),但验证表单数据仍然很痛苦。 Flask-RESTful内置了对使用类似于argparse的库的请求数据验证的支持。

from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate to charge for this resource')
args = parser.parse_args()

注意

与argparse模块不同,reqparse.RequestParser.parse_args()返回一个Python字典而不是自定义数据结构。

使用reqparse模块还可自由提供完整的错误消息。 如果参数未能通过验证,Flask-RESTful将以400错误请求和突出显示错误的响应进行响应。

$ curl -d 'rate=foo' http://127.0.0.1:5000/todos
{'status': 400, 'message': 'foo cannot be converted to int'}

inputs模块提供了一些常用的转换函数,如inputs.date()inputs.url()

使用strict = True调用parse_args可确保在请求包含解析器未定义的参数时引发错误。

args = parser.parse_args(strict=True)

数据格式化

默认情况下,返回迭代器中的所有字段将按原样呈现。 虽然这在你处理Python数据结构时效果很好,但在处理对象时会变得非常令人沮丧。 为了解决这个问题,Flask-RESTful提供了fields模块和marshal_with()装饰器。 与Django ORM和WTForm类似,您可以使用fields模块来描述响应的结构。

from flask_restful import fields, marshal_with

resource_fields = {
    'task':   fields.String,
    'uri':    fields.Url('todo_ep')
}

class TodoDao(object):
    def __init__(self, todo_id, task):
        self.todo_id = todo_id
        self.task = task

        # This field will not be sent in the response
        self.status = 'active'

class Todo(Resource):
    @marshal_with(resource_fields)
    def get(self, **kwargs):
        return TodoDao(todo_id='my_todo', task='Remember the milk')

上面的例子使用一个python对象并且准备将其序列化。 marshal_with()修饰器将应用resource_fields描述的转换。 从对象中提取的唯一字段是task fields.Url字段是一个特殊字段,它接收端点名称并在响应中为该端点生成一个URL。 您需要的许多字段类型都已包含在内。 有关完整列表,请参阅fields指南。

完整示例

将这个例子保存在api.py中

from flask import Flask
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

TODOS = {
    'todo1': {'task': 'build an API'},
    'todo2': {'task': '?????'},
    'todo3': {'task': 'profit!'},
}


def abort_if_todo_doesnt_exist(todo_id):
    if todo_id not in TODOS:
        abort(404, message="Todo {} doesn't exist".format(todo_id))

parser = reqparse.RequestParser()
parser.add_argument('task')


# Todo
# shows a single todo item and lets you delete a todo item
class Todo(Resource):
    def get(self, todo_id):
        abort_if_todo_doesnt_exist(todo_id)
        return TODOS[todo_id]

    def delete(self, todo_id):
        abort_if_todo_doesnt_exist(todo_id)
        del TODOS[todo_id]
        return '', 204

    def put(self, todo_id):
        args = parser.parse_args()
        task = {'task': args['task']}
        TODOS[todo_id] = task
        return task, 201


# TodoList
# shows a list of all todos, and lets you POST to add new tasks
class TodoList(Resource):
    def get(self):
        return TODOS

    def post(self):
        args = parser.parse_args()
        todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
        todo_id = 'todo%i' % todo_id
        TODOS[todo_id] = {'task': args['task']}
        return TODOS[todo_id], 201

##
## Actually setup the Api resource routing here
##
api.add_resource(TodoList, '/todos')
api.add_resource(Todo, '/todos/<todo_id>')


if __name__ == '__main__':
    app.run(debug=True)

用法示例

$ python api.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader

GET列表

$ curl http://localhost:5000/todos
{"todo1": {"task": "build an API"}, "todo3": {"task": "profit!"}, "todo2": {"task": "?????"}}

GET 单个任务

$ curl http://localhost:5000/todos/todo3
{"task": "profit!"}

DELETE 一个任务

$ curl http://localhost:5000/todos/todo2 -X DELETE -v

> DELETE /todos/todo2 HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
> Host: localhost:5000
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 204 NO CONTENT
< Content-Type: application/json
< Content-Length: 0
< Server: Werkzeug/0.8.3 Python/2.7.2
< Date: Mon, 01 Oct 2012 22:10:32 GMT

添加一个新任务

$ curl http://localhost:5000/todos -d "task=something new" -X POST -v

> POST /todos HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
> Host: localhost:5000
> Accept: */*
> Content-Length: 18
> Content-Type: application/x-www-form-urlencoded
>
* HTTP 1.0, assume close after body
< HTTP/1.0 201 CREATED
< Content-Type: application/json
< Content-Length: 25
< Server: Werkzeug/0.8.3 Python/2.7.2
< Date: Mon, 01 Oct 2012 22:12:58 GMT
<
* Closing connection #0
{"task": "something new"}

更新任务

$ curl http://localhost:5000/todos/todo3 -d "task=something different" -X PUT -v

> PUT /todos/todo3 HTTP/1.1
> Host: localhost:5000
> Accept: */*
> Content-Length: 20
> Content-Type: application/x-www-form-urlencoded
>
* HTTP 1.0, assume close after body
< HTTP/1.0 201 CREATED
< Content-Type: application/json
< Content-Length: 27
< Server: Werkzeug/0.8.3 Python/2.7.3
< Date: Mon, 01 Oct 2012 22:13:00 GMT
<
* Closing connection #0
{"task": "something different"}

请求解析

警告

Flask-RESTful的整个请求解析器部分将被移除,并且将被关于如何与更好地执行输入/输出内容的其他包(如marshmallow)集成的文档所取代。 这意味着它将保持到2.0,但认为它已被弃用。 不要担心,如果您现在有代码使用该代码并希望继续这样做,则不会过早消失。

Flask-RESTful的请求解析接口reqparseargparse接口之后建模。 它旨在为Flask中的flask.request对象上的任何变量提供简单且一致的访问。

基本参数

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

from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate cannot be converted')
parser.add_argument('name')
args = parser.parse_args()

注意

默认参数类型是一个unicode字符串。 这将在python3中为str且python2中为unicode

If you specify the help value, it will be rendered as the error message when a type error is raised while parsing it. If you do not specify a help message, the default behavior is to return the message from the type error itself. See error-messages for more details.

By default, arguments are not required. Also, arguments supplied in the request that are not part of the RequestParser will be ignored.

Also note: Arguments declared in your request parser but not set in the request itself will default to None.

Required Arguments

To require a value be passed for an argument, just add required=True to the call to add_argument().

parser.add_argument('name', required=True,
help="Name cannot be blank!")

Multiple Values & Lists

If you want to accept multiple values for a key as a list, you can pass action='append'

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

This will let you make queries like

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

And your args will look like this

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

Other Destinations

If for some reason you’d like your argument stored under a different name once it’s parsed, you can use the dest keyword argument.

parser.add_argument('name', dest='public_name')

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

Argument Locations

By default, the RequestParser tries to parse values from flask.Request.values, and flask.Request.json.

Use the location argument to add_argument() to specify alternate locations to pull the values from. Any variable on the flask.Request can be used. For example:

# 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')

Note

Only use type=list when location='json'. See this issue for more details

Multiple Locations

Multiple argument locations can be specified by passing a list to location:

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

When multiple locations are specified, the arguments from all locations specified are combined into a single MultiDict. The last location listed takes precedence in the result set.

If the argument location list includes the headers location the argument names will no longer be case insensitive and must match their title case names (see str.title()). Specifying location='headers' (not as a list) will retain case insensitivity.

Parser Inheritance

Often you will make a different parser for each resource you write. The problem with this is if parsers have arguments in common. Instead of rewriting arguments you can write a parent parser containing all the shared arguments and then extend the parser with copy(). You can also overwrite any argument in the parent with replace_argument(), or remove it completely with remove_argument(). For example:

from flask_restful 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

Error Handling

The default way errors are handled by the RequestParser is to abort on the first error that occurred. This can be beneficial when you have arguments that might take some time to process. However, often it is nice to have the errors bundled together and sent back to the client all at once. This behavior can be specified either at the Flask application level or on the specific RequestParser instance. To invoke a RequestParser with the bundling errors option, pass in the argument bundle_errors. For example

from flask_restful 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"
    }
}

The application configuration key is “BUNDLE_ERRORS”. For example

from flask import Flask

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

Warning

BUNDLE_ERRORS is a global setting that overrides the bundle_errors option in individual RequestParser instances.

Error Messages

Error messages for each field may be customized using the help parameter to Argument (and also RequestParser.add_argument).

If no help parameter is provided, the error message for the field will be the string representation of the type error itself. If help is provided, then the error message will be the value of help.

help may include an interpolation token, {error_msg}, that will be replaced with the string representation of the type error. This allows the message to be customized while preserving the original error

from flask_restful 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",
    }
}

Output Fields

Flask-RESTful provides an easy way to control what data you actually render in your response. With the fields module, you can use whatever objects (ORM models/custom classes/etc.) you want in your resource. fields also lets you format and filter the response so you don’t have to worry about exposing internal data structures.

It’s also very clear when looking at your code what data will be rendered and how it will be formatted.

Basic Usage

You can define a dict or OrderedDict of fields whose keys are names of attributes or keys on the object to render, and whose values are a class that will format & return the value for that field. This example has three fields: two are String and one is a DateTime, formatted as an RFC 822 date string (ISO 8601 is supported as well)

from flask_restful import Resource, fields, marshal_with

resource_fields = {
    'name': fields.String,
    'address': fields.String,
    'date_updated': fields.DateTime(dt_format='rfc822'),
}

class Todo(Resource):
    @marshal_with(resource_fields, envelope='resource')
    def get(self, **kwargs):
        return db_get_todo()  # Some function that queries the db

This example assumes that you have a custom database object (todo) that has attributes name, address, and date_updated. Any additional attributes on the object are considered private and won’t be rendered in the output. An optional envelope keyword argument is specified to wrap the resulting output.

The decorator marshal_with is what actually takes your data object and applies the field filtering. The marshalling can work on single objects, dicts, or lists of objects.

Note

marshal_with is a convenience decorator, that is functionally equivalent to

class Todo(Resource):
    def get(self, **kwargs):
        return marshal(db_get_todo(), resource_fields), 200

This explicit expression can be used to return HTTP status codes other than 200 along with a successful response (see abort() for errors).

Renaming Attributes

Often times your public facing field name is different from your internal field name. To configure this mapping, use the attribute keyword argument.

fields = {
    'name': fields.String(attribute='private_name'),
    'address': fields.String,
}

A lambda (or any callable) can also be specified as the attribute

fields = {
    'name': fields.String(attribute=lambda x: x._private_name),
    'address': fields.String,
}

Nested properties can also be accessed with attribute

fields = {
    'name': fields.String(attribute='people_list.0.person_dictionary.name'),
    'address': fields.String,
}

Default Values

If for some reason your data object doesn’t have an attribute in your fields list, you can specify a default value to return instead of None.

fields = {
    'name': fields.String(default='Anonymous User'),
    'address': fields.String,
}

Custom Fields & Multiple Values

Sometimes you have your own custom formatting needs. You can subclass the fields.Raw class and implement the format function. This is especially useful when an attribute stores multiple pieces of information. e.g. a bit-field whose individual bits represent distinct values. You can use fields to multiplex a single attribute to multiple output values.

This example assumes that bit 1 in the flags attribute signifies a “Normal” or “Urgent” item, and bit 2 signifies “Read” or “Unread”. These items might be easy to store in a bitfield, but for a human readable output it’s nice to convert them to seperate string fields.

class UrgentItem(fields.Raw):
    def format(self, value):
        return "Urgent" if value & 0x01 else "Normal"

class UnreadItem(fields.Raw):
    def format(self, value):
        return "Unread" if value & 0x02 else "Read"

fields = {
    'name': fields.String,
    'priority': UrgentItem(attribute='flags'),
    'status': UnreadItem(attribute='flags'),
}

Url & Other Concrete Fields

Flask-RESTful includes a special field, fields.Url, that synthesizes a uri for the resource that’s being requested. This is also a good example of how to add data to your response that’s not actually present on your data object.:

class RandomNumber(fields.Raw):
    def output(self, key, obj):
        return random.random()

fields = {
    'name': fields.String,
    # todo_resource is the endpoint name when you called api.add_resource()
    'uri': fields.Url('todo_resource'),
    'random': RandomNumber,
}

By default fields.Url returns a relative uri. To generate an absolute uri that includes the scheme, hostname and port, pass the keyword argument absolute=True in the field declaration. To override the default scheme, pass the scheme keyword argument:

fields = {
    'uri': fields.Url('todo_resource', absolute=True)
    'https_uri': fields.Url('todo_resource', absolute=True, scheme='https')
}

Complex Structures

You can have a flat structure that marshal() will transform to a nested structure

>>> from flask_restful import fields, marshal
>>> import json
>>>
>>> resource_fields = {'name': fields.String}
>>> resource_fields['address'] = {}
>>> resource_fields['address']['line 1'] = fields.String(attribute='addr1')
>>> resource_fields['address']['line 2'] = fields.String(attribute='addr2')
>>> resource_fields['address']['city'] = fields.String
>>> resource_fields['address']['state'] = fields.String
>>> resource_fields['address']['zip'] = fields.String
>>> data = {'name': 'bob', 'addr1': '123 fake street', 'addr2': '', 'city': 'New York', 'state': 'NY', 'zip': '10468'}
>>> json.dumps(marshal(data, resource_fields))
'{"name": "bob", "address": {"line 1": "123 fake street", "line 2": "", "state": "NY", "zip": "10468", "city": "New York"}}'

Note

The address field doesn’t actually exist on the data object, but any of the sub-fields can access attributes directly from the object as if they were not nested.

List Field

You can also unmarshal fields as lists

>>> from flask_restful import fields, marshal
>>> import json
>>>
>>> resource_fields = {'name': fields.String, 'first_names': fields.List(fields.String)}
>>> data = {'name': 'Bougnazal', 'first_names' : ['Emile', 'Raoul']}
>>> json.dumps(marshal(data, resource_fields))
>>> '{"first_names": ["Emile", "Raoul"], "name": "Bougnazal"}'

Advanced : Nested Field

While nesting fields using dicts can turn a flat data object into a nested response, you can use Nested to unmarshal nested data structures and render them appropriately.

>>> from flask_restful import fields, marshal
>>> import json
>>>
>>> address_fields = {}
>>> address_fields['line 1'] = fields.String(attribute='addr1')
>>> address_fields['line 2'] = fields.String(attribute='addr2')
>>> address_fields['city'] = fields.String(attribute='city')
>>> address_fields['state'] = fields.String(attribute='state')
>>> address_fields['zip'] = fields.String(attribute='zip')
>>>
>>> resource_fields = {}
>>> resource_fields['name'] = fields.String
>>> resource_fields['billing_address'] = fields.Nested(address_fields)
>>> resource_fields['shipping_address'] = fields.Nested(address_fields)
>>> address1 = {'addr1': '123 fake street', 'city': 'New York', 'state': 'NY', 'zip': '10468'}
>>> address2 = {'addr1': '555 nowhere', 'city': 'New York', 'state': 'NY', 'zip': '10468'}
>>> data = { 'name': 'bob', 'billing_address': address1, 'shipping_address': address2}
>>>
>>> json.dumps(marshal_with(data, resource_fields))
'{"billing_address": {"line 1": "123 fake street", "line 2": null, "state": "NY", "zip": "10468", "city": "New York"}, "name": "bob", "shipping_address": {"line 1": "555 nowhere", "line 2": null, "state": "NY", "zip": "10468", "city": "New York"}}'

This example uses two Nested fields. The Nested constructor takes a dict of fields to render as sub-fields. The important difference between the Nested constructor and nested dicts (previous example), is the context for attributes. In this example, billing_address is a complex object that has its own fields and the context passed to the nested field is the sub-object instead of the original data object. In other words: data.billing_address.addr1 is in scope here, whereas in the previous example data.addr1 was the location attribute. Remember: Nested and List objects create a new scope for attributes.

Use Nested with List to marshal lists of more complex objects:

user_fields = {
    'id': fields.Integer,
    'name': fields.String,
}

user_list_fields = {
    fields.List(fields.Nested(user_fields)),
}

Extending Flask-RESTful

We realize that everyone has different needs in a REST framework. Flask-RESTful tries to be as flexible as possible, but sometimes you might find that the builtin functionality is not enough to meet your needs. Flask-RESTful has a few different extension points that can help in that case.

Content Negotiation

Out of the box, Flask-RESTful is only configured to support JSON. We made this decision to give API maintainers full control of over API format support; so a year down the road you don’t have to support people using the CSV representation of your API you didn’t even know existed. To add additional mediatypes to your API, you’ll need to declare your supported representations on the Api object.

app = Flask(__name__)
api = Api(app)

@api.representation('application/json')
def output_json(data, code, headers=None):
    resp = make_response(json.dumps(data), code)
    resp.headers.extend(headers or {})
    return resp

These representation functions must return a Flask Response object.

Note

Flask-RESTful uses the json module from the Python standard library instead of flask.json because the Flask JSON serializer includes serialization capabilities which are not in the JSON spec. If your application needs these customizations, you can replace the default JSON representation with one using the Flask JSON module as described above.

It is possible to configure how the default Flask-RESTful JSON representation will format JSON by providing a RESTFUL_JSON attribute on the application configuration. This setting is a dictionary with keys that correspond to the keyword arguments of json.dumps().

class MyConfig(object):
    RESTFUL_JSON = {'separators': (', ', ': '),
                    'indent': 2,
                    'cls': MyCustomEncoder}

Note

If the application is running in debug mode (app.debug = True) and either sort_keys or indent are not declared in the RESTFUL_JSON configuration setting, Flask-RESTful will provide defaults of True and 4 respectively.

Custom Fields & Inputs

One of the most common additions to Flask-RESTful is to define custom types or fields based on your own data types.

Fields

Custom output fields let you perform your own output formatting without having to modify your internal objects directly. All you have to do is subclass Raw and implement the format() method:

class AllCapsString(fields.Raw):
    def format(self, value):
        return value.upper()


# example usage
fields = {
    'name': fields.String,
    'all_caps_name': AllCapsString(attribute=name),
}
Inputs

For parsing arguments, you might want to perform custom validation. Creating your own input types lets you extend request parsing with ease.

def odd_number(value):
    if value % 2 == 0:
        raise ValueError("Value is not odd")

    return value

The request parser will also give you access to the name of the argument for cases where you want to reference the name in the error message.

def odd_number(value, name):
    if value % 2 == 0:
        raise ValueError("The parameter '{}' is not odd. You gave us the value: {}".format(name, value))

    return value

You can also convert public parameter values to internal representations:

# maps the strings to their internal integer representation
# 'init' => 0
# 'in-progress' => 1
# 'completed' => 2

def task_status(value):
    statuses = [u"init", u"in-progress", u"completed"]
    return statuses.index(value)

Then you can use these custom input types in your RequestParser:

parser = reqparse.RequestParser()
parser.add_argument('OddNumber', type=odd_number)
parser.add_argument('Status', type=task_status)
args = parser.parse_args()

Response Formats

To support other representations (xml, csv, html), you can use the representation() decorator. You need to have a reference to your API.

api = Api(app)

@api.representation('text/csv')
def output_csv(data, code, headers=None):
    pass
    # implement csv output!

These output functions take three parameters, data, code, and headers

data is the object you return from your resource method, code is the HTTP status code that it expects, and headers are any HTTP headers to set in the response. Your output function should return a flask.Response object.

def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""
    resp = make_response(json.dumps(data), code)
    resp.headers.extend(headers or {})
    return resp

Another way to accomplish this is to subclass the Api class and provide your own output functions.

class Api(restful.Api):
    def __init__(self, *args, **kwargs):
        super(Api, self).__init__(*args, **kwargs)
        self.representations = {
            'application/xml': output_xml,
            'text/html': output_html,
            'text/csv': output_csv,
            'application/json': output_json,
        }

Resource Method Decorators

There is a property on the Resource class called method_decorators. You can subclass the Resource and add your own decorators that will be added to all method functions in resource. For instance, if you want to build custom authentication into every request.

def authenticate(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if not getattr(func, 'authenticated', True):
            return func(*args, **kwargs)

        acct = basic_authentication()  # custom account lookup function

        if acct:
            return func(*args, **kwargs)

        flask_restful.abort(401)
    return wrapper


class Resource(flask_restful.Resource):
    method_decorators = [authenticate]   # applies to all inherited resources

Alternatively, you can specify a dictionary of iterables that map to HTTP methods and the decorators will only apply to matching requests.

def cache(f):
    @wraps(f)
    def cacher(*args, **kwargs):
        # caching stuff
    return cacher

class MyResource(restful.Resource):
    method_decorators = {'get': [cache]}

     def get(self, *args, **kwargs):
        return something_interesting(*args, **kwargs)

     def post(self, *args, **kwargs):
        return create_something(*args, **kwargs)

In this case, the caching decorator would only apply to the GET request and not the POST request.

Since Flask-RESTful Resources are actually Flask view objects, you can also use standard flask view decorators.

Custom Error Handlers

Error handling is a tricky problem. Your Flask application may be wearing multiple hats, yet you want to handle all Flask-RESTful errors with the correct content type and error syntax as your 200-level requests.

Flask-RESTful will call the handle_error() function on any 400 or 500 error that happens on a Flask-RESTful route, and leave other routes alone. You may want your app to return an error message with the correct media type on 404 Not Found errors; in which case, use the catch_all_404s parameter of the Api constructor.

app = Flask(__name__)
api = flask_restful.Api(app, catch_all_404s=True)

Then Flask-RESTful will handle 404s in addition to errors on its own routes.

Sometimes you want to do something special when an error occurs - log to a file, send an email, etc. Use the got_request_exception() method to attach custom error handlers to an exception.

def log_exception(sender, exception, **extra):
    """ Log an exception to our logging framework """
    sender.logger.debug('Got exception during processing: %s', exception)

from flask import got_request_exception
got_request_exception.connect(log_exception, app)
Define Custom Error Messages

You may want to return a specific message and/or status code when certain errors are encountered during a request. You can tell Flask-RESTful how you want to handle each error/exception so you won’t have to fill your API code with try/except blocks.

errors = {
    'UserAlreadyExistsError': {
        'message': "A user with that username already exists.",
        'status': 409,
    },
    'ResourceDoesNotExist': {
        'message': "A resource with that ID no longer exists.",
        'status': 410,
        'extra': "Any extra information you want.",
    },
}

Including the ‘status’ key will set the Response’s status code. If not specified it will default to 500.

Once your errors dictionary is defined, simply pass it to the Api constructor.

app = Flask(__name__)
api = flask_restful.Api(app, errors=errors)

Intermediate Usage

This page covers building a slightly more complex Flask-RESTful app that will cover out some best practices when setting up a real-world Flask-RESTful-based API. The Quickstart section is great for getting started with your first Flask-RESTful app, so if you’re new to Flask-RESTful you’d be better off checking that out first.

Project Structure

There are many different ways to organize your Flask-RESTful app, but here we’ll describe one that scales pretty well with larger apps and maintains a nice level organization.

The basic idea is to split your app into three main parts: the routes, the resources, and any common infrastructure.

Here’s an example directory structure:

myapi/
    __init__.py
    app.py          # this file contains your app and routes
    resources/
        __init__.py
        foo.py      # contains logic for /Foo
        bar.py      # contains logic for /Bar
    common/
        __init__.py
        util.py     # just some common infrastructure

The common directory would probably just contain a set of helper functions to fulfill common needs across your application. It could also contain, for example, any custom input/output types your resources need to get the job done.

In the resource files, you just have your resource objects. So here’s what foo.py might look like:

from flask_restful import Resource

class Foo(Resource):
    def get(self):
        pass
    def post(self):
        pass

The key to this setup lies in app.py:

from flask import Flask
from flask_restful import Api
from myapi.resources.foo import Foo
from myapi.resources.bar import Bar
from myapi.resources.baz import Baz

app = Flask(__name__)
api = Api(app)

api.add_resource(Foo, '/Foo', '/Foo/<str:id>')
api.add_resource(Bar, '/Bar', '/Bar/<str:id>')
api.add_resource(Baz, '/Baz', '/Baz/<str:id>')

As you can imagine with a particularly large or complex API, this file ends up being very valuable as a comprehensive list of all the routes and resources in your API. You would also use this file to set up any config values (before_request(), after_request()). Basically, this file configures your entire API.

The things in the common directory are just things you’d want to support your resource modules.

Use With Blueprints

See Modular Applications with Blueprints in the Flask documentation for what blueprints are and why you should use them. Here’s an example of how to link an Api up to a Blueprint.

from flask import Flask, Blueprint
from flask_restful import Api, Resource, url_for

app = Flask(__name__)
api_bp = Blueprint('api', __name__)
api = Api(api_bp)

class TodoItem(Resource):
    def get(self, id):
        return {'task': 'Say "Hello, World!"'}

api.add_resource(TodoItem, '/todos/<int:id>')
app.register_blueprint(api_bp)

Note

Calling Api.init_app() is not required here because registering the blueprint with the app takes care of setting up the routing for the application.

Full Parameter Parsing Example

Elsewhere in the documentation, we’ve described how to use the reqparse example in detail. Here we’ll set up a resource with multiple input parameters that exercise a larger amount of options. We’ll define a resource named “User”.

from flask_restful import fields, marshal_with, reqparse, Resource

def email(email_str):
    """Return email_str if valid, raise an exception in other case."""
    if valid_email(email_str):
        return email_str
    else:
        raise ValueError('{} is not a valid email'.format(email_str))

post_parser = reqparse.RequestParser()
post_parser.add_argument(
    'username', dest='username',
    location='form', required=True,
    help='The user\'s username',
)
post_parser.add_argument(
    'email', dest='email',
    type=email, location='form',
    required=True, help='The user\'s email',
)
post_parser.add_argument(
    'user_priority', dest='user_priority',
    type=int, location='form',
    default=1, choices=range(5), help='The user\'s priority',
)

user_fields = {
    'id': fields.Integer,
    'username': fields.String,
    'email': fields.String,
    'user_priority': fields.Integer,
    'custom_greeting': fields.FormattedString('Hey there {username}!'),
    'date_created': fields.DateTime,
    'date_updated': fields.DateTime,
    'links': fields.Nested({
        'friends': fields.Url('user_friends'),
        'posts': fields.Url('user_posts'),
    }),
}

class User(Resource):

    @marshal_with(user_fields)
    def post(self):
        args = post_parser.parse_args()
        user = create_user(args.username, args.email, args.user_priority)
        return user

    @marshal_with(user_fields)
    def get(self, id):
        args = post_parser.parse_args()
        user = fetch_user(id)
        return user

As you can see, we create a post_parser specifically to handle the parsing of arguments provided on POST. Let’s step through the definition of each argument.

post_parser.add_argument(
    'username', dest='username',
    location='form', required=True,
    help='The user\'s username',
)

The username field is the most normal out of all of them. It takes a string from the POST body and converts it to a string type. This argument is required (required=True), which means that if it isn’t provided, Flask-RESTful will automatically return a 400 with a message along the lines of ‘the username field is required’.

post_parser.add_argument(
    'email', dest='email',
    type=email, location='form',
    required=True, help='The user\'s email',
)

The email field has a custom type of email. A few lines earlier we defined an email function that takes a string and returns it if the type is valid, else it raises an exception, exclaiming that the email type was invalid.

post_parser.add_argument(
    'user_priority', dest='user_priority',
    type=int, location='form',
    default=1, choices=range(5), help='The user\'s priority',
)

The user_priority type takes advantage of the choices argument. This means that if the provided user_priority value doesn’t fall in the range specified by the choices argument (in this case [0, 1, 2, 3, 4]), Flask-RESTful will automatically respond with a 400 and a descriptive error message.

That covers the inputs. We also defined some interesting field types in the user_fields dictionary to showcase a couple of the more exotic types.

user_fields = {
    'id': fields.Integer,
    'username': fields.String,
    'email': fields.String,
    'user_priority': fields.Integer,
    'custom_greeting': fields.FormattedString('Hey there {username}!'),
    'date_created': fields.DateTime,
    'date_updated': fields.DateTime,
    'links': fields.Nested({
        'friends': fields.Url('user_friends', absolute=True),
        'posts': fields.Url('user_friends', absolute=True),
    }),
}

First up, there’s fields.FormattedString.

'custom_greeting': fields.FormattedString('Hey there {username}!'),

This field is primarily used to interpolate values from the response into other values. In this instance, custom_greeting will always contain the value returned from the username field.

Next up, check out fields.Nested.

'links': fields.Nested({
    'friends': fields.Url('user_friends', absolute=True),
    'posts': fields.Url('user_posts', absolute=True),
}),

This field is used to create a sub-object in the response. In this case, we want to create a links sub-object to contain urls of related objects. Note that we passed fields.Nested another dict which is built in such a way that it would be an acceptable argument to marshal() by itself.

Finally, we used the fields.Url field type.

'friends': fields.Url('user_friends', absolute=True),
'posts': fields.Url('user_friends', absolute=True),

It takes as its first parameter the name of the endpoint associated with the urls of the objects in the links sub-object. Passing absolute=True ensures that the generated urls will have the hostname included.

Passing Constructor Parameters Into Resources

Your Resource implementation may require outside dependencies. Those dependencies are best passed-in through the constructor to loosely couple each other. The Api.add_resource() method has two keyword arguments: resource_class_args and resource_class_kwargs. Their values will be forwarded and passed into your Resource implementation’s constructor.

So you could have a Resource:

from flask_restful import Resource

class TodoNext(Resource):
    def __init__(self, **kwargs):
        # smart_engine is a black box dependency
        self.smart_engine = kwargs['smart_engine']

    def get(self):
        return self.smart_engine.next_todo()

You can inject the required dependency into TodoNext like so:

smart_engine = SmartEngine()

api.add_resource(TodoNext, '/next',
    resource_class_kwargs={ 'smart_engine': smart_engine })

Same idea applies for forwarding args.

API Reference

If you are looking for information on a specific function, class or method, this part of the documentation is for you.

API Docs

flask_restful.marshal(data, fields, envelope=None)

Takes raw data (in the form of a dict, list, object) and a dict of fields to output and filters the data based on those fields.

Parameters:
  • data – the actual object(s) from which the fields are taken from
  • fields – a dict of whose keys will make up the final serialized response output
  • envelope – optional key that will be used to envelop the serialized response
>>> from flask_restful import fields, marshal
>>> data = { 'a': 100, 'b': 'foo' }
>>> mfields = { 'a': fields.Raw }
>>> marshal(data, mfields)
OrderedDict([('a', 100)])
>>> marshal(data, mfields, envelope='data')
OrderedDict([('data', OrderedDict([('a', 100)]))])
flask_restful.marshal_with(fields, envelope=None)

A decorator that apply marshalling to the return values of your methods.

>>> from flask_restful import fields, marshal_with
>>> mfields = { 'a': fields.Raw }
>>> @marshal_with(mfields)
... def get():
...     return { 'a': 100, 'b': 'foo' }
...
...
>>> get()
OrderedDict([('a', 100)])
>>> @marshal_with(mfields, envelope='data')
... def get():
...     return { 'a': 100, 'b': 'foo' }
...
...
>>> get()
OrderedDict([('data', OrderedDict([('a', 100)]))])

see flask_restful.marshal()

flask_restful.marshal_with_field(field)

A decorator that formats the return values of your methods with a single field.

>>> from flask_restful import marshal_with_field, fields
>>> @marshal_with_field(fields.List(fields.Integer))
... def get():
...     return ['1', 2, 3.0]
...
>>> get()
[1, 2, 3]

see flask_restful.marshal_with()

flask_restful.abort(http_status_code, **kwargs)

Raise a HTTPException for the given http_status_code. Attach any keyword arguments to the exception for later processing.

Api

class flask_restful.Api(app=None, prefix='', default_mediatype='application/json', decorators=None, catch_all_404s=False, serve_challenge_on_401=False, url_part_order='bae', errors=None)

应用程序的主要入口点。 您需要使用Flask应用程序对其进行初始化:

>>> app = Flask(__name__)
>>> api = restful.Api(app)

或者,您可以使用init_app()在构建Flask应用程序之后设置Flask应用程序。

Parameters:
  • app (flask.Flask or flask.Blueprint) - Flask应用程序对象
  • prefixstr) - 将一个值设为所有路由的前缀,例如v1或2010-04-01
  • default_mediatypestr) - 要返回的默认媒体类型
  • decoratorslist) - 附加到每个资源的装饰器
  • catch_all_404s (bool) – Use handle_error() to handle 404 errors throughout your app
  • serve_challenge_on_401 – Whether to serve a challenge response to clients on receiving 401. This usually leads to a username/password popup in web browers.
  • url_part_order – A string that controls the order that the pieces of the url are concatenated when the full url is constructed. ‘b’ is the blueprint (or blueprint registration) prefix, ‘a’ is the api prefix, and ‘e’ is the path component the endpoint is added with
  • errors () – A dictionary to define a custom response for each exception or error raised during a request
add_resource(resource, *urls, **kwargs)

向api添加资源。

参数:
  • resourceResource) - 资源的类名称
  • urls (str) - 要匹配资源的一个或多个url路由,应用标准flask路由规则。 任何url变量都会作为参数传递给资源方法。
  • endpoint (str) - 端点名称(默认为Resource.__name__.lower()可用于在fields.Url字段
  • resource_class_args元组) - 要转发给资源构造函数的参数。
  • resource_class_kwargsdict) - 将kwargs转发给资源的构造函数。

以上未指定的其他关键字参数将按原样传递给flask.Flask.add_url_rule()

例子:

api.add_resource(HelloWorld, '/', '/hello')
api.add_resource(Foo, '/foo', endpoint="foo")
api.add_resource(FooSpecial, '/special/foo', endpoint="foo")
error_router(original_handler, e)

This function decides whether the error occured in a flask-restful endpoint or not. If it happened in a flask-restful endpoint, our handler will be dispatched. If it happened in an unrelated view, the app’s original error handler will be dispatched. In the event that the error occurred in a flask-restful endpoint but the local handler can’t resolve the situation, the router will fall back onto the original_handler as last resort.

Parameters:
  • original_handler (function) – the original Flask error handler for the app
  • e (Exception) – the exception raised while handling the request
handle_error(e)

API的错误处理程序将引发的异常转换为Flask响应,并带有适当的HTTP状态码和正文。

Parameters:eException) - 引发的Exception对象
init_app(app)

使用给定的flask.Flask应用程序或flask.Blueprint对象初始化此类。

参数:appflask.Blueprint) - Flask应用程序或蓝图对象

例子:

api = Api()
api.add_resource(...)
api.init_app(app)
make_response(data, *args, **kwargs)

为请求的媒体类型查找表示变换器,调用变换器创建响应对象。 如果找不到所请求的媒体类型的变换器,则此缺省值为default_mediatype。 如果default_mediatype为None,则按照RFC 2616第14.1节的规定发送406 Not Acceptable响应

Parameters:data - 包含要转换的响应数据的Python对象
mediatypes()

返回Accept标头中发送的请求介体类型列表

mediatypes_method()

Return a method that returns a list of mediatypes

output(resource)

Wraps a resource (as a flask view function), for cases where the resource does not directly return a response object

Parameters:resource – The resource as a flask view function
owns_endpoint(endpoint)

Tests if an endpoint name (not path) belongs to this Api. Takes in to account the Blueprint name part of the endpoint name.

Parameters:endpoint – The name of the endpoint being checked
Returns:bool
representation(mediatype)

Allows additional representation transformers to be declared for the api. Transformers are functions that must be decorated with this method, passing the mediatype the transformer represents. Three arguments are passed to the transformer:

  • The data to be represented in the response body
  • The http status code
  • A dictionary of headers

The transformer should convert the data appropriately for the mediatype and return a Flask response object.

Ex:

@api.representation('application/xml')
def xml(data, code, headers):
    resp = make_response(convert_data_to_xml(data), code)
    resp.headers.extend(headers)
    return resp
resource(*urls, **kwargs)

Wraps a Resource class, adding it to the api. Parameters are the same as add_resource().

Example:

app = Flask(__name__)
api = restful.Api(app)

@api.resource('/foo')
class Foo(Resource):
    def get(self):
        return 'Hello, World!'
unauthorized(response)

Given a response, change it to ask for credentials

url_for(resource, **values)

Generates a URL to the given resource.

Works like flask.url_for().

class flask_restful.Resource

Represents an abstract RESTful resource. Concrete resources should extend from this class and expose methods for each supported HTTP method. If a resource is invoked with an unsupported HTTP method, the API will return a response with status 405 Method Not Allowed. Otherwise the appropriate method is called and passed all arguments from the url rule used when adding the resource to an Api instance. See add_resource() for details.

ReqParse

class reqparse.RequestParser(argument_class=<class 'reqparse.Argument'>, namespace_class=<class 'reqparse.Namespace'>, trim=False, bundle_errors=False)

Enables adding and parsing of multiple arguments in the context of a single request. Ex:

from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('foo')
parser.add_argument('int_bar', type=int)
args = parser.parse_args()
Parameters:
  • trim (bool) – If enabled, trims whitespace on all arguments in this parser
  • bundle_errors (bool) – If enabled, do not abort when first error occurs, return a dict with the name of the argument and the error message to be bundled and return all validation errors
add_argument(*args, **kwargs)

Adds an argument to be parsed.

Accepts either a single instance of Argument or arguments to be passed into Argument’s constructor.

See Argument’s constructor for documentation on the available options.

copy()

Creates a copy of this RequestParser with the same set of arguments

parse_args(req=None, strict=False, http_error_code=400)

Parse all arguments from the provided request and return the results as a Namespace

Parameters:
  • strict – if req includes args not in parser, throw 400 BadRequest exception
  • http_error_code – use custom error code for flask_restful.abort()
remove_argument(name)

Remove the argument matching the given name.

replace_argument(name, *args, **kwargs)

Replace the argument matching the given name with a new version.

class reqparse.Argument(name, default=None, dest=None, required=False, ignore=False, type=<function <lambda>>, location=('json', 'values'), choices=(), action='store', help=None, operators=('=', ), case_sensitive=True, store_missing=True, trim=False, nullable=True)
Parameters:
  • name – Either a name or a list of option strings, e.g. foo or -f, –foo.
  • default – The value produced if the argument is absent from the request.
  • dest – The name of the attribute to be added to the object returned by parse_args().
  • required (bool) – Whether or not the argument may be omitted (optionals only).
  • action – The basic type of action to be taken when this argument is encountered in the request. Valid options are “store” and “append”.
  • ignore – Whether to ignore cases where the argument fails type conversion
  • type – The type to which the request argument should be converted. If a type raises an exception, the message in the error will be returned in the response. Defaults to unicode in python2 and str in python3.
  • location – The attributes of the flask.Request object to source the arguments from (ex: headers, args, etc.), can be an iterator. The last item listed takes precedence in the result set.
  • choices – A container of the allowable values for the argument.
  • help – A brief description of the argument, returned in the response when the argument is invalid. May optionally contain an “{error_msg}” interpolation token, which will be replaced with the text of the error raised by the type converter.
  • case_sensitive (bool) – Whether argument values in the request are case sensitive or not (this will convert all values to lowercase)
  • store_missing (bool) – Whether the arguments default value should be stored if the argument is missing from the request.
  • trim (bool) – If enabled, trims whitespace around the argument.
  • nullable (bool) – If enabled, allows null value in argument.
__init__(name, default=None, dest=None, required=False, ignore=False, type=<function <lambda>>, location=('json', 'values'), choices=(), action='store', help=None, operators=('=', ), case_sensitive=True, store_missing=True, trim=False, nullable=True)
handle_validation_error(error, bundle_errors)

Called when an error is raised while parsing. Aborts the request with a 400 status and an error message

Parameters:
  • error – the error that was raised
  • bundle_errors – do not abort when first error occurs, return a dict with the name of the argument and the error message to be bundled
parse(request, bundle_errors=False)

Parses argument value(s) from the request, converting according to the argument’s type.

Parameters:request – The flask request object to parse arguments from
:param do not abort when first error occurs, return a
dict with the name of the argument and the error message to be bundled
source(request)

Pulls values off the request in the provided location :param request: The flask request object to parse arguments from

Fields

class fields.String(default=None, attribute=None)

Marshal a value as a string. Uses six.text_type so values will be converted to unicode in python2 and str in python3.

format(value)
class fields.FormattedString(src_str)

FormattedString is used to interpolate other values from the response into this field. The syntax for the source string is the same as the string format() method from the python stdlib.

Ex:

fields = {
    'name': fields.String,
    'greeting': fields.FormattedString("Hello {name}")
}
data = {
    'name': 'Doug',
}
marshal(data, fields)
output(key, obj)
class fields.Url(endpoint=None, absolute=False, scheme=None, **kwargs)

A string representation of a Url

Parameters:
  • endpoint (str) – Endpoint name. If endpoint is None, request.endpoint is used instead
  • absolute (bool) – If True, ensures that the generated urls will have the hostname included
  • scheme (str) – URL scheme specifier (e.g. http, https)
output(key, obj)
class fields.DateTime(dt_format='rfc822', **kwargs)

Return a formatted datetime string in UTC. Supported formats are RFC 822 and ISO 8601.

See email.utils.formatdate() for more info on the RFC 822 format.

See datetime.datetime.isoformat() for more info on the ISO 8601 format.

Parameters:dt_format (str) – 'rfc822' or 'iso8601'
format(value)
class fields.Float(default=None, attribute=None)

A double as IEEE-754 double precision. ex : 3.141592653589793 3.1415926535897933e-06 3.141592653589793e+24 nan inf -inf

format(value)
class fields.Integer(default=0, **kwargs)

Field for outputting an integer value.

Parameters:default (int) – The default value for the field, if no value is specified.
format(value)
class fields.Arbitrary(default=None, attribute=None)
A floating point number with an arbitrary precision
ex: 634271127864378216478362784632784678324.23432
format(value)
class fields.Nested(nested, allow_null=False, **kwargs)

Allows you to nest one set of fields inside another. See Advanced : Nested Field for more information

Parameters:
  • nested (dict) – The dictionary to nest
  • allow_null (bool) – Whether to return None instead of a dictionary with null keys, if a nested dictionary has all-null keys
  • kwargs – If default keyword argument is present, a nested dictionary will be marshaled as its value if nested dictionary is all-null keys (e.g. lets you return an empty JSON object instead of null)
output(key, obj)
class fields.List(cls_or_instance, **kwargs)

Field for marshalling lists of other fields.

See List Field for more information.

Parameters:cls_or_instance – The field type the list will contain.
format(value)
output(key, data)
class fields.Raw(default=None, attribute=None)

Raw provides a base field class from which others should extend. It applies no formatting by default, and should only be used in cases where data does not need to be formatted before being serialized. Fields should throw a MarshallingException in case of parsing problem.

Parameters:
  • default – The default value for the field, if no value is specified.
  • attribute – If the public facing value differs from the internal value, use this to retrieve a different attribute from the response than the publicly named value.
format(value)

Formats a field’s value. No-op by default - field classes that modify how the value of existing object keys should be presented should override this and apply the appropriate formatting.

Parameters:value – The value to format
Raises:MarshallingException – In case of formatting problem

Ex:

class TitleCase(Raw):
    def format(self, value):
        return unicode(value).title()
output(key, obj)

Pulls the value for the given key from the object, applies the field’s formatting and returns the result. If the key is not found in the object, returns the default value. Field classes that create values which do not require the existence of the key in the object should override this and return the desired value.

Raises:MarshallingException – In case of formatting problem
class fields.Boolean(default=None, attribute=None)

用于输出布尔值的字段。

空集合,如“”{}[]等将被转换为False

format(value)
class fields.Fixed(decimals=5, **kwargs)

具有固定精度的十进制数字。

format(value)
fields.Price

Fixed的别名

Inputs

inputs.boolean(value)

将字符串“true”“false”解析为布尔型(不区分大小写)。 也分别接受“1”“0”作为TrueFalse(单独的)。 如果输入来自请求JSON正文,则该类型已经是本机python布尔值,并且将不经进一步解析而通过。

inputs.date(value)

以YYYY-mm-dd的格式解析有效的日期

inputs.datetime_from_iso8601(datetime_str)

将ISO8601格式的日期转换为日期时间对象。

例:

inputs.datetime_from_iso8601("2012-01-01T23:30:00+02:00")
Parameters:datetime_strstr) - 要转换的符合ISO8601的字符串
Returns:日期时间
inputs.datetime_from_rfc822(datetime_str)

将RFC822格式的日期转换为日期时间对象。

例:

inputs.datetime_from_rfc822("Wed, 02 Oct 2002 08:00:00 EST")
Parameters:datetime_strstr) - 要转换的符合RFC822的字符串
Returns:日期时间
class inputs.int_range(low, high, argument='argument')

将输入限制为一个范围内的整数(包含)

inputs.iso8601interval(value, argument='argument')

将ISO 8601格式的日期时间间隔分析为日期时间的元组。

使用开始/结束或开始/持续时间表示法接受单个日期(时间)或完整时间间隔,并具有以下行为:

  • 间隔定义为包含开始,独占结束
  • 单日期时间被转换为跨越输入值中未指定的最大分辨率的时间间隔,直至当天。
  • The smallest accepted resolution is 1 second.
  • All timezones are accepted as values; returned datetimes are localized to UTC. Naive inputs and date inputs will are assumed UTC.

例子:

"2013-01-01" -> datetime(2013, 1, 1), datetime(2013, 1, 2)
"2013-01-01T12" -> datetime(2013, 1, 1, 12), datetime(2013, 1, 1, 13)
"2013-01-01/2013-02-28" -> datetime(2013, 1, 1), datetime(2013, 2, 28)
"2013-01-01/P3D" -> datetime(2013, 1, 1), datetime(2013, 1, 4)
"2013-01-01T12:00/PT30M" -> datetime(2013, 1, 1, 12), datetime(2013, 1, 1, 12, 30)
"2013-01-01T06:00/2013-01-01T12:00" -> datetime(2013, 1, 1, 6), datetime(2013, 1, 1, 12)
Parameters:str) - ISO8601日期时间为字符串
Returns:两个UTC日期时间,指定时间间隔的开始和结束
Return type:元组(datetimedatetime
Raises:ValueError,如果间隔无效。
inputs.natural(value, argument='argument')

将输入类型限制为自然数(0,1,2,3 ...)

inputs.positive(value, argument='argument')

将输入类型限制为正整数(1,2,3 ...)

class inputs.regex(pattern, flags=0)

基于正则表达式验证字符串。

例:

parser = reqparse.RequestParser()
parser.add_argument('example', type=inputs.regex('^[0-9]+$'))

如果example参数包含除数字之外的任何内容,则它将被拒绝。

参数:
  • patternstr) - 输入必须匹配的正则表达式
  • flagsint) - 用于更改表达式行为的标志
inputs.url(value)

验证 URL。

Parameters:valuestring) - 要验证的URL
Returns:该URL如果有效。
Raises:ValueError

其他注意事项

查看Flask的许可证以获取有关该项目的法律信息。

运行测试

包含Makefile用于设置运行测试的virtualenv中。 你所需要做的就是运行:

$ make test

要更改用于运行测试的Python版本(默认为Python 2.7),请更改Makefile顶部的PYTHON_MAJORPYTHON_MINOR

您可以在所有支持的版本上运行:

$ make test-all

单独的测试可以使用以下格式的命令来运行:

nosetests <filename>:ClassName.func_name

例:

$ source env/bin/activate
$ nosetests tests/test_reqparse.py:ReqParseTestCase.test_parse_choices_insensitive

或者,如果您在Github上将更改推送到您的分支,Travis会自动为您的分支运行测试。

还提供了一个Tox配置文件,因此您可以在本地测试多个Python版本(2.6,2.7,3.3和3.4)

$ tox