【问题标题】:Python Flask, how to set content typePython Flask,如何设置内容类型
【发布时间】:2012-07-31 04:21:23
【问题描述】:

我正在使用 Flask,并从 get 请求中返回一个 XML 文件。如何将内容类型设置为 xml?

例如

@app.route('/ajax_ddl')
def ajax_ddl():
    xml = 'foo'
    header("Content-type: text/xml")
    return xml

【问题讨论】:

    标签: python flask


    【解决方案1】:

    试试这样:

    from flask import Response
    @app.route('/ajax_ddl')
    def ajax_ddl():
        xml = 'foo'
        return Response(xml, mimetype='text/xml')
    

    实际的 Content-Type 基于 mimetype 参数和字符集(默认为 UTF-8)。

    响应(和请求)对象记录在此处:http://werkzeug.pocoo.org/docs/wrappers/

    【讨论】:

    • 是否可以在全局级别设置这些和其他选项(即:默认)?
    • @earthmeLon,创建flask.Response的子类,覆盖default_mimetype类属性,并将其设置为app.response_classwerkzeug.pocoo.org/docs/wrappers/…flask.pocoo.org/docs/api/#flask.Flask.response_class
    • @earthmeLon:如果您像 Simon 指出的那样设置 app.response_class,请记住使用 app.make_response 来获取您的响应实例,例如 pointed out in the answer below
    • 使用浏览器或邮递员的请求可以很好地使用这种方法,但是 curl 不能很好地处理返回的 Response 对象。卷曲只会打印“找到”。使用 curl "return content, status_code, header" 似乎效果更好。
    【解决方案2】:

    就这么简单

    x = "some data you want to return"
    return x, 200, {'Content-Type': 'text/css; charset=utf-8'}
    

    希望对你有帮助

    更新: 使用下面的方法,因为它适用于 python 2.x 和 python 3.x,它消除了“多头”问题(可能发出多个重复的头)。

    from flask import Response
    r = Response(response="TEST OK", status=200, mimetype="application/xml")
    r.headers["Content-Type"] = "text/xml; charset=utf-8"
    return r
    

    【讨论】:

    • 最简单的解决方案。绝对应该是公认的答案
    • 有一个缺点:它只允许您添加标题。当我这样做时,我最终得到了两个 Content-Type 标题作为响应 - 默认一个并添加了一个。
    • @omikron 我已经更新了答案,试试它应该可以工作的新方法。
    • @HarshDaftary 我不清楚哪种方法是新方法,哪种方法是旧方法。请把“这个方法”换成“上面的方法”或者“下面的方法”好吗?
    • @Leo 我添加了所需的说明。
    【解决方案3】:

    我喜欢并赞成@Simon Sapin 的回答。然而,我最终采取了稍微不同的策略,并创建了自己的装饰器:

    from flask import Response
    from functools import wraps
    
    def returns_xml(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            r = f(*args, **kwargs)
            return Response(r, content_type='text/xml; charset=utf-8')
        return decorated_function
    

    并这样使用它:

    @app.route('/ajax_ddl')
    @returns_xml
    def ajax_ddl():
        xml = 'foo'
        return xml
    

    我觉得这样舒服一点。

    【讨论】:

    • 当返回一个响应和一个像return 'msg', 200这样的状态码时,这将导致ValueError: Expected bytes。相反,将装饰器更改为return Response(*r, content_type='whatever')。它将元组解包为参数。不过,感谢您提供优雅的解决方案!
    【解决方案4】:

    使用make_response method 获取您的数据的响应。然后设置mimetype attribute。最后返回这个响应:

    @app.route('/ajax_ddl')
    def ajax_ddl():
        xml = 'foo'
        resp = app.make_response(xml)
        resp.mimetype = "text/xml"
        return resp
    

    如果您直接使用Response,您将失去通过设置app.response_class 来自定义响应的机会。 make_response 方法使用app.responses_class 来制作响应对象。在此您可以创建自己的类,添加使您的应用程序全局使用它:

    class MyResponse(app.response_class):
        def __init__(self, *args, **kwargs):
            super(MyResponse, self).__init__(*args, **kwargs)
            self.set_cookie("last-visit", time.ctime())
    
    app.response_class = MyResponse  
    

    【讨论】:

    • 这基本上是@SimonSapin 接受的答案重新包装。
    • @J0e3gan 谢谢。我已经扩展了我的答案以更好地解释为什么使用 make_response 比使用 Response 更好
    【解决方案5】:
    from flask import Flask, render_template, make_response
    app = Flask(__name__)
    
    @app.route('/user/xml')
    def user_xml():
        resp = make_response(render_template('xml/user.html', username='Ryan'))
        resp.headers['Content-type'] = 'text/xml; charset=utf-8'
        return resp
    

    【讨论】:

    • 我认为这个答案很重要,因为它清楚地说明了如何从 render_template 更改某些内容的标题。
    【解决方案6】:

    你可以试试下面的方法(python3.6.2):

    案例一:

    @app.route('/hello')
    def hello():
    
        headers={ 'content-type':'text/plain' ,'location':'http://www.stackoverflow'}
        response = make_response('<h1>hello world</h1>',301)
        response.headers = headers
        return response
    

    案例二:

    @app.route('/hello')
    def hello():
    
        headers={ 'content-type':'text/plain' ,'location':'http://www.stackoverflow.com'}
        return '<h1>hello world</h1>',301,headers
    

    我正在使用 Flask 。如果你想返回 json,你可以这样写:

    import json # 
    @app.route('/search/<keyword>')
    def search(keyword):
    
        result = Book.search_by_keyword(keyword)
        return json.dumps(result),200,{'content-type':'application/json'}
    
    
    from flask import jsonify
    @app.route('/search/<keyword>')
    def search(keyword):
    
        result = Book.search_by_keyword(keyword)
        return jsonify(result)
    

    【讨论】:

      【解决方案7】:

      通常您不必自己创建 Response 对象,因为 make_response() 会为您处理好。

      from flask import Flask, make_response                                      
      app = Flask(__name__)                                                       
      
      @app.route('/')                                                             
      def index():                                                                
          bar = '<body>foo</body>'                                                
          response = make_response(bar)                                           
          response.headers['Content-Type'] = 'text/xml; charset=utf-8'            
          return response
      

      还有一点,好像没有人提到after_this_request,我想说点什么:

      after_this_request

      在这个请求之后执行一个函数。这对于修改响应对象很有用。该函数传递了响应对象,并且必须返回相同的或新的。

      所以我们可以用after_this_request 来做,代码应该是这样的:

      from flask import Flask, after_this_request
      app = Flask(__name__)
      
      @app.route('/')
      def index():
          @after_this_request
          def add_header(response):
              response.headers['Content-Type'] = 'text/xml; charset=utf-8'
              return response
          return '<body>foobar</body>'
      

      【讨论】:

        猜你喜欢
        • 2013-01-30
        • 2016-09-28
        • 2014-09-11
        • 2012-08-17
        • 2010-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多