Flask api 表示影响所有视图
Flask api representation affects all the views
我需要有两个逻辑相同的视图来响应不同内容类型的相同数据。我使用 Flask RESTful.
APP = flask.Flask(__name__)
API = flask_restful.Api(APP)
@API.representation('text/csv')
def output_csv(data, code, headers=None):
data_is_list = isinstance(data, types.ListType)
keys = data[0].keys() if data_is_list else data.keys()
output = io.BytesIO()
writer = csv.DictWriter(output, keys)
writer.writeheader()
encode = lambda v: v.encode('utf-8') if isinstance(
v, types.UnicodeType) else v
if data_is_list:
writer.writerows([{k: encode(v) for k, v in i.items()} for i in data])
else:
writer.writerow({k: encode(v) for k, v in data.items()})
resp = flask.make_response(output.getvalue(), code)
resp.headers.extend(headers or {})
return resp
class BaseAction(flask_restful.Resource):
def get(self, id=None):
# ...
return actions[0] if id else actions # Dict or list of dicts.
class ActionAsCSV(BaseAction):
def get(self, id=None):
data = super(ActionAsCSV, self).get(id, closed)
flask.Response(data, mimetype='text/csv')
return data
有几个问题。在我添加了表示视图之后,所有视图 return text/csv 数据都具有适当的 header。 如何使用第一个视图 class 到 return application/json 数据和第二个视图到 return text/csv 数据?第二个问题是 CSV get 方法的 return 值,如果我 return 响应 object return flask.Response(data, mimetype='text/csv')
数据变得格式错误 - 只有键没有值。 如何在不损坏数据的情况下启用不同的 mimetype?
首先,请注意您不应将相同的资源用于 return 单个操作或操作列表。您应该使用两种不同的资源:
class Action(flask_restful.Resource):
def get(self, action_id):
return actions[action_id]
class ActionList(flask_restful.Resource):
def get(self):
return actions
那么,return 同一资源的不同媒体类型的最简单方法是使用内容协商。在这种情况下,您无需声明专用资源 ActionAsCSV
来专门处理 return 以 CSV 格式响应的情况。例如,使用 curl:
的内容协商
curl -iH "Accept: text/csv" http://URL_TO_YOUR_VIEW
此外,Flask-RESTful会自动为您添加正确的content-type header returned 回复:您不需要在资源的 get
方法中定义它。
此外,API 默认配置为 JSON 中的 return 表示。但是,您可以按如下方式修改它:
api = flask_restful.Api(app, default_mediatype="text/csv")
如果您绝对想要两个不同的资源来处理 application/json 或 text/csv,则不使用内容协商且无后备媒体类型,这是可能的:
api = flask_restful.Api(app, default_mediatype=None)
class ActionListMixin(object):
def get(self):
return actions
class JsonActionList(ActionListMixin, flask_restful.Resource):
representations = {'application/json': output_json}
class CsvActionList(ActionListMixin, flask_restful.Resource):
representations = {'text/csv': output_csv}
另一个类似的选项是在添加资源时定义表示转换器:
api = flask_restful.Api(app, default_mediatype=None)
class ActionList(flask_restful.Resource):
def __init__(self, representations=None):
self.representations = representations
super(ActionList, self).__init__()
def get(self):
return actions
api.add_resource(ActionList, '/actions_json', resource_class_kwargs={'representations': {'application/json': output_json}})
api.add_resource(ActionList, '/actions_csv', resource_class_kwargs={'representations': {'text/csv': output_csv}})
我需要有两个逻辑相同的视图来响应不同内容类型的相同数据。我使用 Flask RESTful.
APP = flask.Flask(__name__)
API = flask_restful.Api(APP)
@API.representation('text/csv')
def output_csv(data, code, headers=None):
data_is_list = isinstance(data, types.ListType)
keys = data[0].keys() if data_is_list else data.keys()
output = io.BytesIO()
writer = csv.DictWriter(output, keys)
writer.writeheader()
encode = lambda v: v.encode('utf-8') if isinstance(
v, types.UnicodeType) else v
if data_is_list:
writer.writerows([{k: encode(v) for k, v in i.items()} for i in data])
else:
writer.writerow({k: encode(v) for k, v in data.items()})
resp = flask.make_response(output.getvalue(), code)
resp.headers.extend(headers or {})
return resp
class BaseAction(flask_restful.Resource):
def get(self, id=None):
# ...
return actions[0] if id else actions # Dict or list of dicts.
class ActionAsCSV(BaseAction):
def get(self, id=None):
data = super(ActionAsCSV, self).get(id, closed)
flask.Response(data, mimetype='text/csv')
return data
有几个问题。在我添加了表示视图之后,所有视图 return text/csv 数据都具有适当的 header。 如何使用第一个视图 class 到 return application/json 数据和第二个视图到 return text/csv 数据?第二个问题是 CSV get 方法的 return 值,如果我 return 响应 object return flask.Response(data, mimetype='text/csv')
数据变得格式错误 - 只有键没有值。 如何在不损坏数据的情况下启用不同的 mimetype?
首先,请注意您不应将相同的资源用于 return 单个操作或操作列表。您应该使用两种不同的资源:
class Action(flask_restful.Resource):
def get(self, action_id):
return actions[action_id]
class ActionList(flask_restful.Resource):
def get(self):
return actions
那么,return 同一资源的不同媒体类型的最简单方法是使用内容协商。在这种情况下,您无需声明专用资源 ActionAsCSV
来专门处理 return 以 CSV 格式响应的情况。例如,使用 curl:
curl -iH "Accept: text/csv" http://URL_TO_YOUR_VIEW
此外,Flask-RESTful会自动为您添加正确的content-type header returned 回复:您不需要在资源的 get
方法中定义它。
此外,API 默认配置为 JSON 中的 return 表示。但是,您可以按如下方式修改它:
api = flask_restful.Api(app, default_mediatype="text/csv")
如果您绝对想要两个不同的资源来处理 application/json 或 text/csv,则不使用内容协商且无后备媒体类型,这是可能的:
api = flask_restful.Api(app, default_mediatype=None)
class ActionListMixin(object):
def get(self):
return actions
class JsonActionList(ActionListMixin, flask_restful.Resource):
representations = {'application/json': output_json}
class CsvActionList(ActionListMixin, flask_restful.Resource):
representations = {'text/csv': output_csv}
另一个类似的选项是在添加资源时定义表示转换器:
api = flask_restful.Api(app, default_mediatype=None)
class ActionList(flask_restful.Resource):
def __init__(self, representations=None):
self.representations = representations
super(ActionList, self).__init__()
def get(self):
return actions
api.add_resource(ActionList, '/actions_json', resource_class_kwargs={'representations': {'application/json': output_json}})
api.add_resource(ActionList, '/actions_csv', resource_class_kwargs={'representations': {'text/csv': output_csv}})