Lập Trình Flask-RESTful (Cơ Bản)
  • 🚀Giới Thiệu
  • 🤖Khởi tạo trợ lý AI cùng học lập trình
  • 💻Cài đặt môi trường lập trình
  • 🤩Hello World! - Làm quen với Flask-RESTful
  • ➡️Xử lý yêu cầu (Request parsing)
  • ⬅️Xử lý phản hồi (Output fields)
Powered by GitBook
On this page
  • Làm quen với module reqparse
  • Đối số bắt buộc
  • Đối số đa trị
  • Đổi tên đối số sau khi xử lý
  • Xử lý đối số theo trường dữ liệu
  • Kế thừa Parser (Parser Inheritance)
  • Kiểm soát lỗi (Error Handling)
  • Tổng kết

Xử lý yêu cầu (Request parsing)

Chương này trình bày cách sử dụng module reqparse để xử lý (parse) đối số/danh sách đối số đầu vào (arguments) của một yêu cầu (request). Để thuận tiện trong việc trình bày, chúng tôi sẽ sử dụng một số thuật ngữ tiếng Anh sau: parse (xử lý), argument (đối số), request (yêu cầu).


Làm quen với module reqparse

Đoạn mã nguồn bên dưới trình bày một ví dụ cách khai báo và sử dụng module reqparse để trích xuất hai đối số là rate kiểu int, và name kiểu str. Trong module reqparse, trường hợp không chỉ định kiểu dữ liệu, thì mặc định là kiểu dữ liệu chuỗi - str. Khai báo help trong đoạn mã nguồn được dùng để thông báo lỗi khi phát sinh lỗi sai kiểu dữ liệu.

from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate cannot be converted')
parser.add_argument('name')
args = parser.parse_args()

Đối số bắt buộc

Đối số bắt buộc (Require arguments) là kỹ thuật buộc một request phải bao gồm giá trị (value) cho một thuộc tính được chỉ định. Điều này được thực hiện qua khai báo required=True.

parser.add_argument('name', required=True, help="Name is a required argument!")

Đối số đa trị

Đối số đa trị (Multiple values) là kỹ thuật cho phép một tham số được truyền vào nhiều giá trị. Điều này được thực hiện qua khai báo action='append'. Kết quả sau khi xử lý (parse) là một mảng chứa các giá trị được truyền vào.

parser.add_argument('name', action='append')

Khai báo này cho phép một yêu cầu (request) có cấu trúc như sau:

$ curl http://127.0.0.1:5000/ -d "name=anna" -d "name=bob" -d "name=chris"

Kết quả sau khi xử lý (parse) có dạng như sau:

args = parser.parse_args()
args['name']    # ['anna', 'bob', 'chris']

Đổi tên đối số sau khi xử lý

Đổi tên đối số sau khi xử lý, được dịch từ thuật ngữ "Other Destinations", là kỹ thuật cho phép thay đổi tên của đối số sau khi xử lý (parse), được chỉ thị qua khai báo dest='new_name'.

parser.add_argument('name', dest='public_name')

args = parser.parse_args()
args['public_name']

Xử lý đối số theo trường dữ liệu

Argument Locations - Xử lý đối số theo trường dữ liệu là kỹ thuật cho phép xử lý đối số đầu vào từ nhiều trường dữ liệu khác nhau, thông qua khai báo location='...', chẳng hạn, User-Agent, session_id. Một cách tổng quát, tất cả các trường dữ liệu được hỗ trợ bởi flask.Request đều có thể được sử dụng trong phương thức add_argument().

Một số thuộc tính và phương thức quan trọng của flask.Request:

  • method: Xác định phương thức HTTP của yêu cầu (GET, POST, PUT, DELETE, ...).

  • args: Chứa các đối số được gửi từ client.

  • form: Lưu trữ dữ liệu được gửi từ form.

  • json: Truy cập dữ liệu JSON được gửi từ client (nếu có).

  • headers: Lưu trữ các dữ liệu headers của yêu cầu.

  • cookies: Chứa thông tin về các cookies được gửi cùng yêu cầu.

  • files: Danh sách các file được gửi đến server.

  • url: URL mà yêu cầu được gửi đến.


Promtp tham khảo: Hãy giải thích module "flask.Request" trong nền tảng Flask một cách ngắn gọn dễ hiễu.

# Look only in the POST body
parser.add_argument('name', type=int, location='form')

# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')

# From the request headers
parser.add_argument('User-Agent', location='headers')

# From http cookies
parser.add_argument('session_id', location='cookies')

# From file uploads
parser.add_argument('picture', type=werkzeug.datastructures.FileStorage, location='files')

Đoạn mã nguồn trên trình bày một số trường dữ liệu mà một đối tượng parser có thể truy cập. Lưu ý rằng, nếu location='json' thì phải sử dụng kèm với kiểu dữ liệu type=list.

Khai báo location trong phương thức add_argument() còn có thể nhận dữ liệu dạng mảng để xử lý từ nhiều trường dữ liệu khác nhau, được gọi là xử lý đa trường dữ liệu (Multiple Locations), như ví dụ bên dưới.

parser.add_argument('text', location=['headers', 'values'])

Trong thư viện Werkzeug, MultiDict là một cấu trúc dữ liệu tương tự như dict trong Python, nhưng nó cho phép lưu trữ nhiều giá trị cho cùng một key (khóa). Điều này khác biệt so với từ điển thông thường, vì khi bạn thêm một giá trị mới cho một key đã tồn tại trong MultiDict, giá trị mới sẽ được thêm vào một danh sách các giá trị của key đó.

Một số đặc điểm quan trọng của MultiDict:

  1. Lưu trữ nhiều giá trị cho cùng một key: Cho phép bạn gán nhiều giá trị cho một key duy nhất, điều này hữu ích trong việc xử lý dữ liệu từ các yêu cầu HTTP với các đối số trùng lặp.

  2. Hỗ trợ các phương thức như get(), getlist(), setlist(), và remove(): Các phương thức này giúp bạn truy cập, thêm, xóa các giá trị tương ứng với key trong MultiDict.

MultiDict trong Werkzeug là một cấu trúc dữ liệu hiệu quả, giúp quản lý dữ liệu có cấu trúc từ các yêu cầu HTTP, đặc biệt là khi có sự trùng lặp giữa các đối số.


Prompt tham khảo: Trong thư viện werkzeug, hãy giải thích cấu trúc dữ liệu "MultiDict" một cách ngắn gọn.

Kế thừa Parser (Parser Inheritance)

from flask_restful import reqparse

# Parent parser
parser = reqparse.RequestParser()
parser.add_argument('foo', type=int)

# Extended parser
# parser_copy has both 'foo' and 'bar'
parser_copy = parser.copy()
parser_copy.add_argument('bar', type=int)

parser_copy.replace_argument('foo', required=True, location='json')
# 'foo' is now a required str located in json,
# not an int as defined by the original parser

# parser_copy no longer has 'foo' argument
parser_copy.remove_argument('foo')

Kiểm soát lỗi (Error Handling)

from flask_restful import reqparse

parser = reqparse.RequestParser(bundle_errors=True)
parser.add_argument('foo', type=int, required=True)
parser.add_argument('bar', type=int, required=True)

# If a request comes in not containing both 'foo' and 'bar',
# the error that will come back will look something like this.
#{
#    "message":  {
#        "foo": "foo error message",
#        "bar": "bar error message"
#    }
#}


# The default behavior would only return the first error
parser = RequestParser()
parser.add_argument('foo', type=int, required=True)
parser.add_argument('bar', type=int, required=True)

#{
#    "message":  {
#        "foo": "foo error message"
#    }
#}

Tham số BUNDLE_ERRORS có thể được cấu hình ở cấp độ ứng dụng Flask, bằng cách khai báo như sau:

from flask import Flask

app = Flask(__name__)
app.config['BUNDLE_ERRORS'] = True

Bên cạnh tính năng gom lỗi (bundle errors), các parser của module reqparse còn hỗ trợ gửi thông báo lỗi thông qua tham số help, bằng cách kết hợp thêm với chỉ thị {error_msg}.

from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument(
    'foo',
    choices=('one', 'two'),
    help='Bad choice: {error_msg}'
)

# If a request comes in with a value of "three" for 'foo':
#{
#    "message":  {
#        "foo": "Bad choice: three is not a valid choice",
#    }
#}

Tổng kết

Chương này đã trình bày các kỹ thuật xử lý đối số đầu vào của một yêu cầu - request parsing - thông qua module reqparse. Chương tiếp theo sẽ trình bày các kỹ thuật xử lý phản hồi (response) cho mỗi yêu cầu (request) từ client.

PreviousHello World! - Làm quen với Flask-RESTfulNextXử lý phản hồi (Output fields)

Last updated 1 year ago

Module flask.Request trong Flask là một thành phần quan trọng cho phép truy cập các thông tin liên quan đến yêu cầu HTTP được gửi từ client tới server. Module này cung cấp các phương thức và thuộc tính để trích xuất thông tin từ yêu cầu HTTP như thông tin về URL, dữ liệu form, headers, cookies, method (phương thức HTTP), và nhiều thông tin khác.

Danh sách các đối số, nếu sử dụng kỹ thuật Multiple Locations, sẽ được lưu trữ theo cấu trúc dữ liệu MultiDict được định nghĩa trong lớp .

Thường thì bạn sẽ định nghĩa các parser khác nhau cho mỗi tài nguyên (resource). Vấn đề của điều này là nếu các parser chia sẻ các đối số chung, như vậy, thay vì viết lại các parser, chúng ta có thể viết một parser chung (parent parser) chứa tất cả các đối số chung và sau đó mở rộng (extend) parser đó với phương thức copy(). Chúng ta cũng có thể ghi đè lên bất kỳ đối số nào trong parser chung bằng cách sử dụng phương thức replace_argument(), hoặc loại bỏ nó hoàn toàn với phương thức remove_argument().

Cách mặc định để RequestParser xử lý lỗi là tự động dừng lại khi gặp lỗi đầu tiên. Điều này có thể hữu ích khi có nhiều đối số, dẫn đến việc có thể mất thời gian để xử lý. Tuy nhiên, việc gom nhóm các lỗi lại và gửi tất cả về client cùng một lúc được xem là giải pháp tốt hơn. Tính nắng này có thể được chỉ định ở cấp độ ứng dụng Flask hoặc trên các parser cụ thể. Để sử dụng RequestParser với tùy chọn gom lỗi, bạn có thể truyền đối số bundle_errors.

🤖
🤖
🤖
werkzeug.datastructures.MultiDict
➡️
Page cover image