Python Flask, içerik türü nasıl ayarlanır


176

Flask kullanıyorum ve bir get isteği bir XML dosyası döndürür. İçerik türünü xml olarak nasıl ayarlarım?

Örneğin

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

Yanıtlar:


255

Şunu deneyin:

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

Gerçek Content-Type, mimetype parametresini ve karakter kümesini temel alır (varsayılan değer UTF-8'dir).

Yanıt (ve istek) nesneleri burada belgelenmiştir: http://werkzeug.pocoo.org/docs/wrappers/


1
Bunları ve diğer seçenekleri küresel düzeyde ayarlamak mümkün müdür (örn: varsayılan)?
earthmeLon

10
@earthmeLon, bir alt sınıf yapın flask.Response, default_mimetypesınıf niteliğini geçersiz kılın ve bunu app.response_class werkzeug.pocoo.org/docs/wrappers/… flask.pocoo.org/docs/api/#flask.Flask.response_class
Simon Sapin

@earthmeLon: app.response_classSimon'un işaret ettiği gibi davranırsanız , aşağıdaki yanıtta belirtildiğiapp.make_response gibi yanıt örneğinizi almak için kullanmayı unutmayın .
Martin Geisler

Tarayıcılardan veya postacılardan gelen istekler bu yaklaşımla iyi çalışır, ancak kıvrılma döndürülen Yanıt nesnesiyle iyi çalışmaz. Curl sadece "Bulundu" yazdıracaktır. Curl ile "iade içeriği, status_code, başlık" daha iyi çalışıyor gibi görünüyor.
fuma

144

Bu kadar basit

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

Umarım yardımcı olur

Güncelleme: Bu yöntemi hem python 2.x hem de python 3.x ile çalışacağı için kullanın

ve ikincisi birden çok başlık sorununu da ortadan kaldırır.

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
En basit çözüm. Kesinlikle kabul edilen cevap olmalı
Ömer Dagan

Bir dezavantaj var: sadece üstbilgi EKLE. Bunu yaptığımda, yanıt olarak iki Content-Type başlığı ile sonuçlandım - varsayılan olan ve bir tane ekledim.
omikron

1
@omikron Cevabı güncelledim, çalışması gereken yeni yöntemi deneyin.
Sert Daftary

48

@Simon Sapin'in cevabını beğendim ve yanıtladım. Bununla birlikte, biraz farklı bir çakışma aldı ve kendi dekoratörümü oluşturdum:

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

ve bu şekilde kullanın:

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

Bence bu biraz daha rahat.


3
Hem yanıt hem de benzer bir durum kodu döndürürken return 'msg', 200, bu yol açacaktır ValueError: Expected bytes. Bunun yerine dekoratörü olarak değiştirin return Response(*r, content_type='whatever'). Tuple, argümanlara açılacaktır. Zarif bir çözüm için teşekkürler!
Felix

24

Verilerinize yanıt almak için make_response yöntemini kullanın . Sonra mimetype özniteliğini ayarlayın . Son olarak şu yanıtı döndürün:

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

ResponseDoğrudan kullanırsanız , yanıtları ayarlayarak özelleştirme şansını kaybedersiniz app.response_class. make_responseMetodu, app.responses_classtepki nesne yapmak için. Burada kendi sınıfınızı oluşturabilir, uygulamanızın onu global olarak kullanmasını sağlayabilirsiniz:

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  

Bu aslında @ SimonSapin'in kabul edilen cevabı yeniden paketlenmiştir.
J0e3gan

@ J0e3gan teşekkürler. Kullanmanın neden kullanmaktan make_responsedaha iyi olduğunu daha iyi açıklamak için cevabımı genişlettimResponse
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
Bence bu cevap önemli çünkü bir şey üzerindeki başlıkları bir render_template'den nasıl değiştireceğimizi netleştiriyor.
Bir Hettinger

5

Genellikle Responsenesneyi kendiniz oluşturmak zorunda değilsiniz, çünkü sizin için make_response()bununla ilgilenecektir.

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

Bir şey daha var, kimsenin bahsetmediği anlaşılıyor, bir after_this_requestşey söylemek istiyorum:

after_this_request

Bu istekten sonra bir işlev yürütür. Bu, yanıt nesnelerini değiştirmek için kullanışlıdır. İşlev yanıt nesnesinden geçirilir ve aynı veya yenisini döndürmek zorundadır.

böylece bunu yapabiliriz after_this_request, kod şöyle görünmelidir:

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

Aşağıdaki yöntemi deneyebilirsiniz (python3.6.2) :

birinci durum :

@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

ikinci durum :

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

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

Ben Flask kullanıyorum. Ve json dönmek istiyorsanız, bunu yazabilirsiniz:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.