我需要有两个逻辑上相同的视图来响应不同内容类型中的相同数据。我使用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
有几个问题。添加表示视图后,所有视图都返回带有apprpriate标头的text / csv数据。 如何使用第一个视图类返回application / json数据,第二个返回text / csv数据?第二个问题是CSV get方法的返回值,如果我返回响应对象{{1数据变得格式错误 - 只有没有值的键。 如何启用不同的mimetype而不会造成数据损坏?
答案 0 :(得分:3)
首先,请注意,您不应使用相同的资源来返回单个操作或操作列表。您应该使用两种不同的资源:
class Action(flask_restful.Resource):
def get(self, action_id):
return actions[action_id]
class ActionList(flask_restful.Resource):
def get(self):
return actions
然后,为同一资源返回不同媒体类型的最简单方法是使用内容协商。在这种情况下,您无需声明专用资源ActionAsCSV
来专门处理以CSV格式返回响应的情况。例如,要与 curl :
curl -iH "Accept: text/csv" http://URL_TO_YOUR_VIEW
此外, Flask-RESTful 会自动在返回的响应中为您添加正确的内容类型标头:您无需在{{1}中定义它你资源的方法。
此外,API默认配置为以JSON格式返回表示。但是,您可以修改如下:
get
如果你绝对想要两个不同的资源来处理 application / json 或 text / csv ,使用内容协商并且没有后备媒体类型,这是可能的:< / p>
api = flask_restful.Api(app, default_mediatype="text/csv")
Anoter类似的选项是在添加资源时定义表示变换器:
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}