Python Flask、コンテンツタイプの設定方法


176

Flaskを使用していて、getリクエストからXMLファイルを返します。コンテンツタイプをxmlに設定するにはどうすればよいですか。

例えば

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

回答:


254

このようにしてみてください:

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
これらのオプションおよびその他のオプションをグローバルレベル(つまり、デフォルト)で設定することは可能ですか?
earthmeLon 2013

10
@earthmeLonは、のサブクラスを作りflask.Response、上書きdefault_mimetypeクラス属性を、および設定とapp.response_class werkzeug.pocoo.org/docs/wrappers/... flask.pocoo.org/docs/api/#flask.Flask.response_class
サパンサイモン

@earthmeLon:app.response_classSimonが指摘するように設定した場合は、を使用して、以下の回答で指摘されているapp.make_responseように、応答インスタンスを取得してください。
マーティンガイスラー、2015

ブラウザまたは郵便配達員を使用したリクエストは、このアプローチでは問題なく機能しますが、curlは返されたResponseオブジェクトでは適切に機能しません。Curlは "Found"を出力します。curlでは、「return content、status_code、header」がより適切に機能するようです。
風魔

143

これと同じくらい簡単

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

それが役に立てば幸い

更新:この方法は、python 2.xとpython 3.xの両方で機能するため、使用してください。

第2に、複数のヘッダーの問題も解消されます。

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

欠点があります:ヘッダーを追加することしかできません。私がそれをしたとき、私は応答で2つのContent-Typeヘッダーに終わりました-デフォルトのものと追加されたもの。
omikron 2017

1
@omikron私は答えを更新しました、それがうまくいくはずの新しい方法を試してください。
Harsh Daftary、2017

47

@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')ます。タプルを引数に解凍します。しかし、エレガントな解決策をありがとう!
Felix

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_classmake_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

@ J0e3ganありがとう。私は答えを拡張して、なぜ使用するのが使用するmake_responseよりも優れているのかをよりResponse
詳しく

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から何かのヘッダーを変更する方法が明確になるので、この答えは重要だと思います。
ヘッティンガー2017

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

もう1つ、誰もについて言及し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>'

4

次の方法を試すことができます(python3.6.2):

ケース1:

@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

ケース2:

@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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.