从Flask视图返回任意对象

时间:2014-06-05 09:55:41

标签: python flask

根据Flask.make_response方法的Flask文档,允许从视图返回的唯一类型是app.response_class,str,unicode,wsgi函数或具有响应对象的元组的实例以下之一。

我希望能够从视图中返回我自己的模型和查询,并使通用代码构建适当的响应,将对象序列化为可接受的格式,从查询构建集合,应用过滤条件等。哪个地方最适合这个?

我考虑了以下几种可能性,但无法找到正确的方法。

  • 子类化响应并设置app.response_class
  • 对Flask重新定义Flask.make_response
  • 进行子类化
  • 将app.route包装到另一个装饰器
  • Flask.after_request

edit1 :我已经有许多API,我需要在视图中实现这些行为,但我希望避免在任何地方重复这些行为。

edit2 :我实际构建了一个Flask-extension,其中包含我的应用程序中使用的许多默认实践。虽然一个普通的装饰工作肯定会起作用,但我真的需要更多的魔法。

3 个答案:

答案 0 :(得分:3)

为什么不创建一个函数make_response_from_custom_object并以

结束您的观点
return make_response_from_custom_object(custom_object)

如果它会变得很普遍,我会将它放入@response_from_custom_object装饰器中,但挂钩到Flask似乎有点矫枉过正。你可以链接装饰器,所以包装app.route也没有意义;你需要的只是

@app.route(..)
@response_from_custom_object
def view(...):
    ...

如果你能以简单明了的方式做到这一点,那么就没有必要让你的代码变得神奇,因此不易理解。

答案 1 :(得分:1)

您走的链越远(make_responsedispatch_request + handle_user_errorfull_dispatch_requestrewrite Flask from scratch)您需要恢复的功能越多创建

在这种情况下最简单的方法是覆盖response_class并在那里进行序列化 - 这将为您留下Flask在make_responsefull_dispatch_request等中所做的所有魔力,但仍然可以控制如何响应异常和序列化响应。它还保留了Flask的所有挂钩,因此您的扩展程序的使用者可以覆盖他们需要的行为(并且他们可以重用他们现有的Flask请求/生命周期知识)

答案 2 :(得分:0)

Python本质上是动态的,因此虽然这不是最佳实践,但您可以将应用程序上的make_response方法重新分配给所需的内容。

为避免重新创建默认功能,您可以保存对原始功能的引用,并使用该引用来实现新功能。

我最近在项目中使用了此功能,以添加直接从烧瓶视图返回自定义Serializable类实例的功能。

app = Flask("StarCorp")

__original_make_response = app.make_response


def convert_custom_object(obj):

    # Check if the returned object is "Serializable"
    if not isinstance(obj, Serializable):
        # Nope, do whatever flask normally does
        return __original_make_response(obj)

    # It is, get a `dict` from `obj` using the `json` method
    data = obj.json
    data.pop(TYPE_META)  # Don't share the type meta info of an object with users

    # Let flask turn the `dict` into a `json` response
    return __original_make_response(data)  

app.make_response = convert_custom_object

由于flask扩展通常提供init_app(app)方法,因此我确信您可以构建一个扩展,以类似的方式让猴子修补传入的应用程序对象。