⬅️Xử lý phản hồi (Output fields)
Flask-RESTful hỗ trợ nhiều cơ chế kết xuất dữ liệu (field) trong phản hồi (response) thông qua module fields
. Bên cạnh đó, module này cho phép định dạng phản hồi theo nhu cầu của lập trình viên, điều này giúp hạn chế rò rỉ các cấu trúc dữ liệu của chương trình.
Bắt đầu với module fields
fields
🤖 Bạn có thể sử dụng cấu trúc dữ liệu dict
hoặc OrderedDict
chứa các trường (fields), với key là tên thuộc tính hoặc là một đối tượng để kết xuất (render). Ví dụ bên dưới gồm có ba trường, gồm: hai trường kiểu String
và một trường kiểu DateTime
, được định dạng dưới dạng chuỗi ngày tháng RFC 822 (Flask-RESTful cũng hỗ trợ ISO 8601).
from flask_restful import Resource, fields, marshal_with
resource_fields = {
'name': fields.String,
'address': fields.String,
'date_updated': fields.DateTime(dt_format='rfc822'),
}
class Todo(Resource):
@marshal_with(resource_fields, envelope='resource')
def get(self, **kwargs):
return db_get_todo() # Some function that queries the db
Trong đoạn chương trình trên, phương thức db_get_todo()
sẽ trả về một đối tượng có thể bao gồm các thuộc tính khác, ngoài ba thuộc tính được định nghĩa trong resource_fields
. Module fields
, trong tình huống này, sẽ chỉ kết xuất (render) và trả về những trường dữ liệu được định nghĩa trong resource_fields
, và bỏ qua các thuộc tính khác trong đối tượng được trả về từ phương thức db_get_todo()
.
Đổi tên thuộc tính
Tính năng này cho phép lập trình viên thay đổi tên thuộc tính khi kết xuất dữ liệu (field) cho phía client. Điều này được thực hiện thông qua tham số attribute
.
fields = {
'name': fields.String(attribute='fullname'),
'address': fields.String,
}
Từ khóa attribute
có thể hỗ trợ xử lý hàm vô danh (lambda).
fields = {
'name': fields.String(attribute=lambda x: x._private_name),
'address': fields.String,
}
Các thuộc tính lồng nhau (nested properties) cũng được hỗ trợ.
fields = {
'name': fields.String(attribute='people_list.0.person_dictionary.name'),
'address': fields.String,
}
Giá trị mặc định
Trong một số tình huống, lập trình viên có thể định nghĩa giá trị mặc định cho các trường dữ liệu, thông qua tham số default
.
fields = {
'name': fields.String(default='Anonymous User'),
'address': fields.String,
}
Tạo các field mới (Custom fields)
Kỹ thuật này cho phép mở rộng module fields
để hỗ trợ các định dạng theo nhu cầu của lập trình viên. Điều này được thực hiện đơn giản bằng cách kế thừa (extend) lớp fields.Raw
và hiện thực phương thức format()
.
Đoạn ví dụ mô phỏng hai chức năng trong một ứng dụng Mail. Ví dụ này giả định rằng bit 1
trong thuộc tính flags
biểu thị ý nghĩa "Bình thường" hoặc "Khẩn cấp", và bit 2
biểu thị "Đã đọc" hoặc "Chưa đọc". Các mục này có thể dễ dàng lưu trữ trong một bitfield
, nhưng để người dùng có thể hiểu được ý nghĩa, người lập trình nên chuyển đổi chúng thành các giá trị chuỗi.
class UrgentItem(fields.Raw):
def format(self, value):
return "Urgent" if value & 0x01 else "Normal"
class UnreadItem(fields.Raw):
def format(self, value):
return "Unread" if value & 0x02 else "Read"
fields = {
'name': fields.String,
'priority': UrgentItem(attribute='flags'),
'status': UnreadItem(attribute='flags'),
}
Các trường dữ liệu khác trong module fields
fields
Flask-RESTful cũng bao gồm trường dữ liệu fields.Url
để biễu diễn các đường dẫn Web. Đây là tính năng quan trọng trong việc mở rộng tài nguyên cho một phản hồi (reponse) từ server về client. Chẳng hạn, tính năng phân trang (pagination) thì trường fields.Url
có thể được khai thác để biểu diễn trang liền trước/liền sau.
class RandomNumber(fields.Raw):
def output(self, key, obj):
return random.random()
fields = {
'name': fields.String,
# todo_resource is the endpoint name when you called api.add_resource()
'uri': fields.Url('todo_resource'),
'random': RandomNumber,
}
Thông số absolute
có thể được dùng để trả về một URI tuyệt đối (absolute URI), thay vì một URI tương đối (relative URI).
fields = {
'uri': fields.Url('todo_resource', absolute=True),
'https_uri': fields.Url('todo_resource', absolute=True, scheme='https')
}
Trong đoạn lệnh bên dưới, bạn đọc có thể thực hành nhanh với module fields
của Flask-RESTful trên môi trường CMD hoặc Terminal để biểu diễn các cấu trúc phức tạp (complex structures).
>>> from flask_restful import fields, marshal
>>> import json
>>>
>>> resource_fields = {'name': fields.String}
>>> resource_fields['address'] = {}
>>> resource_fields['address']['line 1'] = fields.String(attribute='addr1')
>>> resource_fields['address']['line 2'] = fields.String(attribute='addr2')
>>> resource_fields['address']['city'] = fields.String
>>> resource_fields['address']['state'] = fields.String
>>> resource_fields['address']['zip'] = fields.String
>>> data = {'name': 'bob', 'addr1': '123 fake street', 'addr2': '', 'city': 'New York', 'state': 'NY', 'zip': '10468'}
>>> json.dumps(marshal(data, resource_fields))
'{"name": "bob", "address": {"line 1": "123 fake street", "line 2": "", "state": "NY", "zip": "10468", "city": "New York"}}'
Module fields
của Flask-RESTful cũng hỗ trợ các trường dữ liệu dạng danh sách (list), như các đoạn lệnh trên môi trường CMD hoặc Terminal sau.
>>> from flask_restful import fields, marshal
>>> import json
>>>
>>> resource_fields = {'name': fields.String, 'first_names': fields.List(fields.String)}
>>> data = {'name': 'Bougnazal', 'first_names' : ['Emile', 'Raoul']}
>>> json.dumps(marshal(data, resource_fields))
>>> '{"first_names": ["Emile", "Raoul"], "name": "Bougnazal"}'
Tổng kết
Chương này đã trình bày các kỹ thuật xử lý xử lý phản hồi (output fields) cho các yêu cầu (request) từ client. Việc xử lý phản hồi được thực hiện thông qua module fields
.
Last updated