Python Flask,如何设置内容类型


176

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

例如

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

Answers:


252

尝试这样:

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/


1
是否可以在全局级别上设置这些选项和其他选项(即:默认值)?
EarthmeL13年

9
@earthmeLon,作为的子类flask.Response,覆盖default_mimetypeclass属性,并将其设置为app.response_class werkzeug.pocoo.org/docs/wrappers/… flask.pocoo.org/docs/api/#flask.Flask.response_class
西蒙Sapin的

@earthmeLon:如果您设置 app.response_class为Simon指出,请记住使用app.make_response来获取您的响应实例,如下面的答案中所指出
马丁·盖斯勒

使用浏览器或邮递员的请求可以使用此方法很好地工作,但是curl不能很好地用于返回的Response对象。Curl只会打印“找到”。使用curl“返回内容,status_code,标头”似乎更好。
fuma

142

就这么简单

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

15
最简单的解决方案。绝对应该是公认的答案
Omer Dagan 2015年

有一个缺点:它只允许您添加标头。完成后,我得到了两个Content-Type标头作为响应-默认一个标头,然后添加了一个。
omikron

1
@omikron我已经更新了答案,请尝试应该使用的新方法。
严苛达夫里

46

我喜欢并赞成@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

我认为这稍微舒适一些。


3
当同时返回响应和状态代码时return 'msg', 200,将导致ValueError: Expected bytes。而是将装饰器更改为return Response(*r, content_type='whatever')。它将把元组解压缩为参数。不过,谢谢您提供的优雅解决方案!
菲利克斯

24

使用make_response方法获取数据响应。然后设置mimetype属性。最后返回此响应:

@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 2015年

@ J0e3gan谢谢。我扩展了答案,以更好地解释为什么使用make_response比使用更好Response
Marianna Vassallo

14
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

2
我认为这个答案很重要,因为它明确了如何更改render_template上的标头。
Hettinger

5

通常,您不必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>'

3

您可以尝试以下方法(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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.