Xử lý dữ liệu yêu cầu đến trong Flask
Trong bất kỳ ứng dụng web nào, bạn sẽ phải xử lý dữ liệu yêu cầu đến từ user . Flask, giống như bất kỳ khuôn khổ web nào khác, cho phép bạn truy cập dữ liệu yêu cầu một cách dễ dàng.
Trong hướng dẫn này, ta sẽ xem xét cách xử lý dữ liệu đến cho các trường hợp sử dụng phổ biến nhất. Các dạng dữ liệu đến mà ta sẽ đề cập là: chuỗi truy vấn, dữ liệu biểu mẫu và đối tượng JSON. Để chứng minh những trường hợp này, ta sẽ xây dựng một ứng dụng mẫu đơn giản với ba tuyến chấp nhận dữ liệu chuỗi truy vấn, dữ liệu biểu mẫu hoặc dữ liệu JSON.
Đối tượng yêu cầu
Để truy cập dữ liệu đến trong Flask, bạn phải sử dụng đối tượng yêu cầu. Đối tượng yêu cầu giữ tất cả dữ liệu đến từ yêu cầu, bao gồm kiểu mimetype, liên kết giới thiệu, địa chỉ IP, dữ liệu thô, phương thức HTTP và tiêu đề, trong số những thứ khác. Mặc dù tất cả thông tin mà đối tượng yêu cầu nắm giữ có thể hữu ích, nhưng trong bài viết này, ta sẽ chỉ tập trung vào dữ liệu thường được cung cấp trực tiếp bởi người gọi của điểm cuối của ta .
Để có quyền truy cập vào đối tượng yêu cầu trong Flask, bạn chỉ cần nhập nó từ thư viện Flask.
from flask import request
Sau đó, bạn có thể sử dụng nó trong bất kỳ chức năng xem nào của bạn .
Khi ta đến phần về chuỗi truy vấn, bạn sẽ thấy đối tượng yêu cầu đang hoạt động.
Ứng dụng mẫu
Để chứng minh các cách sử dụng yêu cầu khác nhau, ta sẽ bắt đầu với một ứng dụng Flask đơn giản. Mặc dù ứng dụng mẫu sử dụng bố cục tổ chức đơn giản cho các chức năng và tuyến chế độ xem, những gì bạn học được trong hướng dẫn này có thể được áp dụng cho bất kỳ phương pháp tổ chức chế độ xem nào của bạn như chế độ xem dựa trên lớp, bản thiết kế hoặc tiện ích mở rộng như Flask-Via.
Để bắt đầu, trước tiên ta cần cài đặt Flask.
pip install Flask
Sau đó, ta có thể bắt đầu với đoạn mã sau.
#app.py
from flask import Flask, request #import main Flask class and request object
app = Flask(__name__) #create the Flask app
@app.route('/query-example')
def query_example():
return 'Todo...'
@app.route('/form-example')
def formexample():
return 'Todo...'
@app.route('/json-example')
def jsonexample():
return 'Todo...'
if _name == '__main_':
app.run(debug=True, port=5000) #run app in debug mode on port 5000
Khởi động ứng dụng bằng:
python app.py
Đoạn mã được cung cấp cài đặt ba tuyến đường với một thông báo cho ta biết 'Todo…'. Ứng dụng sẽ bắt đầu trên cổng 5000, vì vậy bạn có thể xem từng tuyến đường trong trình duyệt của bạn bằng các liên kết sau:
http://127.0.0.1:5000/query-example (hoặc localhost: 5000 / query-example)
http://127.0.0.1:5000/form-example (hoặc localhost: 5000 / form-example)
http://127.0.0.1:5000/json-example (hoặc localhost: 5000 / json-example)
Đối với mỗi trong ba tuyến đường, bạn sẽ thấy điều tương tự:
Đối số truy vấn
Đối số URL mà bạn thêm vào chuỗi truy vấn là cách đơn giản nhất để truyền dữ liệu vào ứng dụng web, vì vậy hãy bắt đầu với chúng.
Chuỗi truy vấn trông giống như sau:
example.com?arg1=value1&arg2=value2
Chuỗi truy vấn bắt đầu sau dấu chấm hỏi (?) Và có hai cặp key-value được phân tách bằng dấu và (&). Đối với mỗi cặp, khóa được theo sau bởi dấu bằng (=) và sau đó là giá trị. Ngay cả khi bạn chưa bao giờ nghe nói về chuỗi truy vấn cho đến bây giờ, bạn chắc chắn đã thấy chúng trên khắp các trang web.
Vì vậy, trong ví dụ đó, ứng dụng nhận được:
arg1 : value1
arg2 : value2
Chuỗi truy vấn hữu ích để chuyển dữ liệu mà không yêu cầu user thực hiện hành động. Bạn có thể tạo một chuỗi truy vấn ở đâu đó trong ứng dụng của bạn và thêm vào đó một URL để khi user đưa ra yêu cầu, dữ liệu sẽ tự động được chuyển cho họ. Một chuỗi truy vấn cũng có thể được tạo bởi các biểu mẫu có GET làm phương thức.
Để tạo chuỗi truy vấn của riêng ta trên tuyến truy vấn-ví dụ, ta sẽ bắt đầu với chuỗi đơn giản sau:
http://127.0.0.1:5000/query-example?language=Python
Nếu bạn chạy ứng dụng và chuyển đến URL đó, bạn sẽ thấy không có gì thay đổi. Đó chỉ là do ta chưa xử lý các đối số truy vấn.
Để làm như vậy, ta cần đọc bằng khóa ngôn ngữ bằng cách sử dụng request.args.get('language')
hoặc request.args['language']
.
Bằng cách gọi request.args.get('language')
, ứng dụng của ta sẽ tiếp tục chạy nếu khóa ngôn ngữ không tồn tại trong URL. Trong trường hợp đó, kết quả của phương thức sẽ là None
. Nếu ta sử dụng request.args['language']
, ứng dụng sẽ trả về lỗi 400 nếu khóa ngôn ngữ không tồn tại trong URL. Đối với chuỗi truy vấn, tôi khuyên bạn nên sử dụng request.args.get()
vì user dễ dàng sửa đổi URL. Nếu họ xóa một trong các khóa, request.args.get()
sẽ ngăn ứng dụng không hoạt động.
Hãy đọc khóa ngôn ngữ và hiển thị nó dưới dạng kết quả . Sửa đổi với định tuyến ví dụ truy vấn mã sau.
@app.route('/query-example')
def query_example():
language = request.args.get('language') #if key doesn't exist, returns None
return '''<h1>The language value is: {}</h1>'''.format(language)
Sau đó, chạy ứng dụng và chuyển đến URL.
Như bạn thấy , đối số từ URL được gán cho biến ngôn ngữ và sau đó được trả về trình duyệt. Trong một ứng dụng thực, bạn có thể cần làm điều gì đó với dữ liệu chứ không chỉ đơn giản là trả lại.
Để thêm nhiều tham số chuỗi truy vấn hơn, ta chỉ thêm ký hiệu và và các cặp key-value mới vào cuối URL. Vì vậy, một cặp bổ sung sẽ giống như sau:
http://127.0.0.1:5000/query-example?language=Python&framework=Flask
Với cặp mới là:
framework : Flask
Và nếu bạn muốn nhiều hơn nữa, hãy tiếp tục thêm ký hiệu và và các cặp key-value . Đây là một ví dụ:
http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=Scotch
Để có quyền truy cập vào các giá trị đó, ta vẫn sử dụng request.args.get()
hoặc request.args[]
. Hãy sử dụng cả hai để chứng minh điều gì sẽ xảy ra khi thiếu khóa. Ta sẽ gán giá trị của kết quả cho các biến và sau đó hiển thị chúng.
@app.route('/query-example')
def query_example():
language = request.args.get('language') #if key doesn't exist, returns None
framework = request.args['framework'] #if key doesn't exist, returns a 400, bad request error
website = request.args.get('website')
return '''<h1>The language value is: {}</h1>
<h1>The framework value is: {}</h1>
<h1>The website value is: {}'''.format(language, framework, website)
Khi bạn chạy nó, bạn sẽ thấy:
Nếu bạn xóa ngôn ngữ khỏi URL, thì bạn sẽ thấy rằng giá trị kết thúc là None
.
Nếu bạn xóa khóa khung, bạn sẽ gặp lỗi.
Đến đây bạn thực hiện và các chuỗi truy vấn, hãy chuyển sang loại dữ liệu đến tiếp theo.
Dữ liệu biểu mẫu
Tiếp theo, ta có dữ liệu biểu mẫu. Dữ liệu biểu mẫu đến từ một biểu mẫu đã được gửi dưới dạng yêu cầu ĐĂNG tới một tuyến đường. Vì vậy, thay vì nhìn thấy dữ liệu trong URL (ngoại trừ trường hợp khi biểu mẫu được gửi với yêu cầu GET), dữ liệu biểu mẫu sẽ được chuyển tới ứng dụng phía sau. Mặc dù bạn không thể dễ dàng nhìn thấy dữ liệu biểu mẫu được chuyển qua, nhưng ứng dụng của bạn vẫn có thể đọc nó.
Để chứng minh điều này, hãy sửa đổi tuyến biểu mẫu để chấp nhận cả yêu cầu GET và POST và trả về một biểu mẫu đơn giản.
@app.route('/form-example', methods=['GET', 'POST']) #allow both GET and POST requests
def form_example():
return '''<form method="POST">
Language: <input type="text" name="language"><br>
Framework: <input type="text" name="framework"><br>
<input type="submit" value="Submit"><br>
</form>'''
Chạy ứng dụng dẫn đến kết quả sau:
Điều quan trọng nhất cần biết về biểu mẫu này là nó thực hiện một yêu cầu ĐĂNG đến cùng một tuyến đường đã tạo biểu mẫu. Các khóa mà ta sẽ đọc trong ứng dụng của bạn đều đến từ thuộc tính "name" trên các đầu vào biểu mẫu của ta . Trong trường hợp của ta , ngôn ngữ và khung là tên của các đầu vào, vì vậy ta sẽ có quyền truy cập vào những thứ đó trong ứng dụng của bạn .
Bên trong chức năng xem, ta cần kiểm tra xem phương thức yêu cầu là GET hay POST. Nếu đó là GET, ta chỉ hiển thị biểu mẫu mà ta có. Nếu đó là POST, thì ta muốn xử lý dữ liệu đến.
Để làm điều đó, hãy thêm một câu lệnh if đơn giản để kiểm tra yêu cầu POST. Nếu phương thức yêu cầu không phải là POST, thì ta biết đó là GET, vì tuyến đường của ta chỉ cho phép hai loại yêu cầu đó. Đối với các yêu cầu GET, biểu mẫu sẽ được tạo.
@app.route('/form-example', methods=['GET', 'POST']) #allow both GET and POST requests
def form_example():
if request.method == 'POST': #this block is only entered when the form is submitted
return 'Submitted form.'
return '''<form method="POST">
Language: <input type="text" name="language"><br>
Framework: <input type="text" name="framework"><br>
<input type="submit" value="Submit"><br>
</form>'''
Bên trong khối, ta sẽ đọc các giá trị đến với request.args.get('language')
và request.form['framework']
. Lưu ý nếu ta có nhiều đầu vào hơn, thì ta có thể đọc thêm dữ liệu.
Thêm mã bổ sung vào tuyến biểu mẫu.
@app.route('/form-example', methods=['GET', 'POST']) #allow both GET and POST requests
def form_example():
if request.method == 'POST': #this block is only entered when the form is submitted
language = request.form.get('language')
framework = request.form['framework']
return '''<h1>The language value is: {}</h1>
<h1>The framework value is: {}</h1>'''.format(language, framework)
return '''<form method="POST">
Language: <input type="text" name="language"><br>
Framework: <input type="text" name="framework"><br>
<input type="submit" value="Submit"><br>
</form>'''
Hãy thử chạy ứng dụng và gửi biểu mẫu.
Tương tự như ví dụ chuỗi truy vấn trước đây, ta có thể sử dụng request.form.get()
thay vì tham chiếu khóa trực tiếp với request.form[]
. request.form.get()
trả về None
thay vì gây ra lỗi 400 khi không tìm thấy khóa.
Như bạn thấy , việc xử lý dữ liệu biểu mẫu đã gửi cũng dễ dàng như việc xử lý các đối số chuỗi truy vấn.
Dữ liệu JSON
Cuối cùng, ta có dữ liệu JSON. Giống như dữ liệu biểu mẫu, nó không dễ nhìn như vậy. Dữ liệu JSON thường được xây dựng bởi một quy trình gọi tuyến của ta . Một đối tượng JSON mẫu trông như thế này:
{
"language" : "Python",
"framework" : "Flask",
"website" : "Scotch",
"version_info" : {
"python" : 3.4,
"flask" : 0.12
},
"examples" : ["query", "form", "json"],
"boolean_test" : true
}
Như bạn thấy với JSON, bạn có thể chuyển dữ liệu phức tạp hơn nhiều mà bạn có thể làm với các chuỗi truy vấn hoặc dữ liệu biểu mẫu. Trong ví dụ này, bạn thấy các đối tượng JSON lồng nhau và một mảng các mục. Với Flask, việc đọc tất cả các giá trị này rất đơn giản.
Đầu tiên, để gửi một đối tượng JSON, ta cần một chương trình có khả năng gửi các yêu cầu tùy chỉnh đến URL. Đối với điều này, ta có thể sử dụng một ứng dụng có tên là Postman .
Tuy nhiên, trước khi ta sử dụng Postman, hãy thay đổi phương thức trên tuyến để chỉ chấp nhận các yêu cầu POST.
@app.route('/json-example', methods=['POST']) #GET requests will be blocked
def json_example():
return 'Todo...'
Sau đó, trong Postman, hãy cài đặt một chút để cho phép gửi các yêu cầu POST.
Trong Người đưa thư, hãy thêm URL và thay đổi loại thành ĐĂNG. Trên tab nội dung, thay đổi thành thô và chọn JSON (ứng dụng / json) từ trình đơn thả xuống. Tất cả điều này được thực hiện để Postman có thể gửi dữ liệu JSON đúng cách và do đó ứng dụng Flask của bạn sẽ hiểu rằng nó đang nhận JSON.
Từ đó, bạn có thể sao chép ví dụ vào phần nhập văn bản. Nó sẽ giống như thế này:
Để kiểm tra, chỉ cần gửi yêu cầu và bạn sẽ nhận được 'Todo…' làm phản hồi vì ta chưa sửa đổi chức năng của bạn .
Để đọc dữ liệu, trước tiên bạn phải hiểu cách Flask dịch dữ liệu JSON sang cấu trúc dữ liệu Python.
Bất cứ thứ gì là đối tượng đều được chuyển đổi thành một lệnh Python. {"key" : "value"}
trong JSON tương ứng với somedict['key']
, trả về một giá trị trong Python.
Một mảng trong JSON được chuyển đổi thành một danh sách trong Python. Vì cú pháp giống nhau nên đây là danh sách ví dụ: [1,2,3,4,5]
Sau đó, các giá trị bên trong dấu ngoặc kép trong đối tượng JSON trở thành chuỗi trong Python. true
và false
trở thành True
and False
trong Python. Cuối cùng, các số không có dấu ngoặc kép xung quanh chúng sẽ trở thành số trong Python.
Bây giờ ta hãy bắt đầu đọc dữ liệu JSON đến.
Đầu tiên, hãy gán mọi thứ từ đối tượng JSON vào một biến bằng cách sử dụng request.get_json()
.
req_data = request.get_json()
request.get_json()
chuyển đổi đối tượng JSON thành dữ liệu Python cho ta . Hãy gán dữ liệu yêu cầu đến cho các biến và trả lại chúng bằng cách áp dụng các thay đổi sau đây đối với tuyến đường json-example của ta .
@app.route('/json-example', methods=['POST']) #GET requests will be blocked
def json_example():
req_data = request.get_json()
language = req_data['language']
framework = req_data['framework']
python_version = req_data['version_info']['python'] #two keys are needed because of the nested object
example = req_data['examples'][0] #an index is needed because of the array
boolean_test = req_data['boolean_test']
return '''
The language value is: {}
The framework value is: {}
The Python version is: {}
The item at index 0 in the example list is: {}
The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)
Nếu ta chạy ứng dụng của bạn và gửi cùng một yêu cầu bằng Postman, ta sẽ nhận được điều này:
Lưu ý cách bạn truy cập các phần tử không ở cấp cao nhất. ['version']['python']
được sử dụng vì bạn đang nhập một đối tượng lồng nhau. Và ['examples'][0]
được sử dụng để truy cập index thứ 0 trong mảng ví dụ.
Nếu đối tượng JSON được gửi cùng với yêu cầu không có khóa được truy cập trong chức năng xem của bạn, thì yêu cầu sẽ không thành công. Nếu bạn không muốn nó bị lỗi khi khóa không tồn tại, bạn sẽ phải kiểm tra xem khóa có tồn tại hay không trước khi cố gắng truy cập nó. Đây là một ví dụ:
language = None
if 'language' in req_data:
language = req_data['language']
Kết luận
Đến đây bạn sẽ hiểu cách sử dụng đối tượng yêu cầu trong Flask để nhận các dạng dữ liệu đầu vào phổ biến nhất. Để tóm tắt lại, ta đã đề cập đến:
- Chuỗi truy vấn
- Dữ liệu biểu mẫu
- Dữ liệu JSON
Với kiến thức này, bạn sẽ không gặp vấn đề gì với bất kỳ dữ liệu nào mà user ném vào ứng dụng của bạn!
Tìm hiểu thêm
Nếu bạn thích hướng dẫn này và muốn tìm hiểu thêm về Flask từ tôi, hãy xem khóa học video Giới thiệu về Flask miễn phí tại trang web Pretty Printed của tôi, khóa học này sẽ đưa bạn từ việc không biết gì về Flask để xây dựng ứng dụng sổ lưu bút. Nếu khóa học đó không ở trình độ của bạn, thì tôi có các khóa học khác trên trang web của bạn mà bạn cũng có thể quan tâm.
Các tin liên quan