Python Flask, cara mengatur tipe konten


176

Saya menggunakan Flask dan saya mengembalikan file XML dari permintaan dapatkan. Bagaimana cara mengatur tipe konten ke xml?

misalnya

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

Jawaban:


255

Coba seperti ini:

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

Content-Type yang sebenarnya didasarkan pada parameter mimetype dan charset (default ke UTF-8).

Objek tanggapan (dan permintaan) didokumentasikan di sini: http://werkzeug.pocoo.org/docs/wrappers/


1
Apakah mungkin untuk mengatur ini dan opsi lain di tingkat global (yaitu: default)?
earthmeLon

10
@earthmeLon, membuat subclass dari flask.Response, menimpa default_mimetypeatribut kelas, dan menetapkan bahwa sebagai app.response_class werkzeug.pocoo.org/docs/wrappers/... flask.pocoo.org/docs/api/#flask.Flask.response_class
Simon Sapin

@earthmeLon: Jika Anda menetapkan app.response_classseperti yang ditunjukkan Simon, jangan lupa gunakan app.make_responseuntuk mendapatkan contoh tanggapan Anda seperti ditunjukkan dalam jawaban di bawah ini .
Martin Geisler

Permintaan dengan peramban atau tukang pos berfungsi baik dengan pendekatan ini, namun ikal tidak berfungsi dengan baik dengan objek Respons yang dikembalikan. Curl hanya akan mencetak "Ditemukan". Dengan ikal "kembalikan konten, status_code, tajuk" tampaknya berfungsi lebih baik.
Fuma

144

Sesederhana ini

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

Semoga ini bisa membantu

Pembaruan: Gunakan metode ini karena ini akan bekerja dengan kedua python 2.x dan python 3.x

dan kedua itu juga menghilangkan beberapa masalah header.

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
Solusi paling sederhana. Pasti jawaban yang diterima
Omer Dagan

Ada kekurangannya: ini memungkinkan Anda hanya ADD header. Ketika saya melakukannya, saya berakhir dengan dua header Tipe Konten sebagai respons - default dan menambahkan satu.
omikron

1
@ Tomikron Saya telah memperbarui jawabannya, coba metode baru yang seharusnya berhasil.
Harsh Daftary

48

Saya suka dan membenarkan jawaban @Simon Sapin. Saya akhirnya mengambil cara yang sedikit berbeda, dan menciptakan dekorator saya sendiri:

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

dan gunakan sebagai berikut:

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

Saya pikir ini sedikit lebih nyaman.


3
Ketika mengembalikan respons dan kode status suka return 'msg', 200, ini akan mengarah ke ValueError: Expected bytes. Alih-alih, ganti dekorator ke return Response(*r, content_type='whatever'). Ini akan membongkar tuple ke argumen. Terima kasih, untuk solusi elegan!
Felix

24

Gunakan metode make_response untuk mendapatkan respons dengan data Anda. Kemudian atur atribut mimetype . Akhirnya kembalikan respons ini:

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

Jika Anda menggunakan Responsesecara langsung, Anda kehilangan kesempatan untuk menyesuaikan respons dengan mengatur app.response_class. The make_responsemetode menggunakan app.responses_classuntuk membuat objek respon. Dalam hal ini Anda dapat membuat kelas Anda sendiri, tambahkan membuat aplikasi Anda menggunakannya secara global:

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  

Ini pada dasarnya adalah jawaban yang diterima @S SimonSapin yang dipaket ulang.
J0e3gan

@ J0e3gan terima kasih. Saya telah memperluas jawaban saya untuk lebih menjelaskan mengapa menggunakan make_responselebih baik daripada menggunakanResponse
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
Saya pikir jawaban ini penting karena menjelaskan cara mengubah header pada sesuatu dari render_template.
A Hettinger

5

Biasanya Anda tidak harus membuat Responseobjek sendiri karena make_response()akan mengurusnya untuk Anda.

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

Satu hal lagi, sepertinya tidak ada yang menyebutkan after_this_request, saya ingin mengatakan sesuatu:

after_this_request

Menjalankan fungsi setelah permintaan ini. Ini berguna untuk memodifikasi objek respons. Fungsi ini melewati objek respons dan harus mengembalikan yang sama atau yang baru.

jadi kita bisa melakukannya dengan after_this_request, kode akan terlihat seperti ini:

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

Anda dapat mencoba metode berikut (python3.6.2) :

satu kasus :

@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

kasus kedua :

@app.route('/hello')
def hello():

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

Saya menggunakan Flask. Dan jika Anda ingin mengembalikan json, Anda dapat menulis ini:

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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.