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
  • Bắt đầu với module fields
  • Đổi tên thuộc tính
  • Giá trị mặc định
  • Tạo các field mới (Custom fields)
  • Các trường dữ liệu khác trong module fields
  • Tổng kết

Xử lý phản hồi (Output fields)

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

Last updated 1 year ago

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

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,
}

Để tìm hiểu thêm về từ khóa lambda, bạn đọc có thể sử dụng gợi ý (promtp) sau: Hãy giải thích giá trị "lamda" trong ngôn ngữ lập trình Python.

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

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')
}

Bạn đọc có thể tương tác với trợ lý AI để hiểu thêm về khái niệm, cũng như so sánh URL và URI.

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.

Trong ngôn ngữ lập trình Python, lambda là một từ khoá để tạo ra hàm vô danh (anonymous function). Hàm vô danh là một hàm không có tên và thường được sử dụng khi cần một hàm đơn giản mà không cần phải đặt tên cho nó.

🤖
🤖
⬅️
Page cover image