Python Flask, cách đặt loại nội dung


176

Tôi đang sử dụng Flask và tôi trả lại một tệp XML từ một yêu cầu get. Làm cách nào để đặt loại nội dung thành xml?

ví dụ

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

Câu trả lời:


254

Hãy thử như thế này:

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

Kiểu nội dung thực tế dựa trên tham số mimetype và bộ ký tự (mặc định là UTF-8).

Các đối tượng phản hồi (và yêu cầu) được ghi lại ở đây: http://werkzeug.pocoo.org/docs/wrappers/


1
Có thể đặt các tùy chọn này và các tùy chọn khác ở cấp độ toàn cầu (nghĩa là: mặc định) không?
earthmeLon

10
@earthmeLon, tạo một lớp con của flask.Response, ghi đè lên các default_mimetypethuộc tính lớp, và thiết lập đó là app.response_class werkzeug.pocoo.org/docs/wrappers/... flask.pocoo.org/docs/api/#flask.Flask.response_class
Simon Sapin

@earthmeLon: Nếu bạn đặt app.response_classnhư Simon chỉ ra, hãy nhớ sử dụng app.make_responseđể lấy ví dụ phản hồi của bạn như được chỉ ra trong câu trả lời dưới đây .
Martin Geisler

Các yêu cầu với trình duyệt hoặc người đưa thư hoạt động tốt với phương pháp này, tuy nhiên curl không hoạt động tốt với đối tượng Phản hồi được trả về. Curl sẽ chỉ in "Tìm thấy". Với curl "return content, status_code, header" dường như hoạt động tốt hơn.
fuma

143

Đơn giản như thế này

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

Hy vọng nó giúp

Cập nhật: Sử dụng phương pháp này vì nó sẽ hoạt động với cả python 2.x và python 3.x

và thứ hai, nó cũng loại bỏ nhiều vấn đề tiêu đề.

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
Giải pháp đơn giản nhất. Chắc chắn phải là câu trả lời được chấp nhận
Omer Dagan

Có một nhược điểm: nó chỉ cho phép bạn THÊM tiêu đề. Khi tôi làm điều đó, tôi đã kết thúc với hai tiêu đề Kiểu Nội dung để phản hồi - mặc định một và thêm một tiêu đề.
omikron

1
@omikron Mình đã cập nhật câu trả lời, hãy thử phương pháp mới nên hoạt động.
Harsh Daftary

47

Tôi thích và nâng cao câu trả lời của @Simon Sapin. Tuy nhiên, cuối cùng tôi đã thực hiện một chiến thuật hơi khác và tạo ra trang trí của riêng mình:

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

và sử dụng nó như vậy:

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

Tôi nghĩ rằng điều này là một chút thoải mái hơn.


3
Khi trả về cả phản hồi và mã trạng thái như thế nào return 'msg', 200, điều này sẽ dẫn đến ValueError: Expected bytes. Thay vào đó, thay đổi trang trí thành return Response(*r, content_type='whatever'). Nó sẽ giải nén bộ dữ liệu để tranh luận. Cảm ơn bạn mặc dù, cho một giải pháp thanh lịch!
Felix

24

Sử dụng phương thức make_response để nhận phản hồi với dữ liệu của bạn. Sau đó đặt thuộc tính mimetype . Cuối cùng trả về phản hồi này:

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

Nếu bạn sử dụng Responsetrực tiếp, bạn sẽ mất cơ hội tùy chỉnh các phản hồi bằng cách cài đặt app.response_class. Các make_responsephương pháp sử dụng app.responses_classđể làm cho các đối tượng phản ứng. Trong phần này, bạn có thể tạo lớp của riêng mình, thêm làm cho ứng dụng của bạn sử dụng nó trên toàn cầu:

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  

Đây thực chất là câu trả lời được chấp nhận của @ SimonSapin được đóng gói lại.
J0e3gan

@ J0e3gan cảm ơn. Tôi đã mở rộng câu trả lời của mình để giải thích rõ hơn lý do tại sao sử dụng make_responsetốt hơn sử dụngResponse
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
Tôi nghĩ rằng câu trả lời này rất quan trọng vì nó làm rõ cách thay đổi các tiêu đề trên một cái gì đó từ render_template.
Một Hettinger

5

Thông thường, bạn không phải tự tạo Responseđối tượng vì make_response()sẽ chăm sóc điều đó cho bạn.

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

Một điều nữa, dường như không ai nhắc đến after_this_request, tôi muốn nói điều gì đó:

after_this_request

Thực hiện một chức năng sau khi yêu cầu này. Điều này rất hữu ích để sửa đổi các đối tượng phản ứng. Hàm được truyền đối tượng phản hồi và phải trả về cùng hoặc một đối tượng mới.

vì vậy chúng ta có thể làm điều đó với after_this_request, mã sẽ trông như thế này:

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

Bạn có thể thử phương pháp sau (python3.6.2)

trường hợp một

@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

trường hợp hai

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

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

Tôi đang sử dụng Flask. Và nếu bạn muốn trả về json, bạn có thể viết điều này:

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.