Flask api表示会影响所有视图

时间:2015-07-27 13:50:14

标签: python rest flask mime-types flask-restful

我需要有两个逻辑上相同的视图来响应不同内容类型中的相同数据。我使用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而不会造成数据损坏?

1 个答案:

答案 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}