Validate dữ liệu là một khâu rất cần thiết trong lập trình, đặc biệt là lập trình web. Trong Python, cũng có rất nhiều thư viện hỗ trợ validation. Trong số đó, Marshmallow là thư viện có tên tuổi. Nào chúng ta cùng khám phá nhé
Introduction
Trang chủ của Marshmallow các bạn có thể tham khảo tại đây: //marshmallow.readthedocs.io/en/3.0/
Ngoài ra, Marshmallow cũng được sử dụng kết hợp với các framework web khác tạo ra các plugin hay extension như:
- //flask-marshmallow.readthedocs.io/en/latest/: Plugin của Flask
- //github.com/marshmallow-code/django-rest-marshmallow: Plugin của Django Rest Framework
Tóm tắt một ngắn gọn một vài features của Marshmallow:
- Validate input data input data
- Deserialize input data to app-level objects. input data to app-level objects.
- Serialize app-level objects to primitive Python types. app-level objects to primitive Python types.
Installation
Marshmallow được public tại đây: //pypi.org/project/marshmallow/ Bạn có thể cài dễ dàng qua
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
9pip install marshmallow
Lastest version tại thời điểm bài viết này là
from marshmallow import Schema, fields
class CustomerSchema[Schema]:
username = fields.Str[]
email = fields.Email[]
created = fields.DateTime[]
0Python version support marshmallow:
- Python 2.6 ++
- Python 3.4 ++
Guide
Trong guide này, mình sẽ chỉ giới thiệu tóm tắt 3 features chính:
- Validation
- Deserialize
- Serialize
Ngoài ra, các bạn có thể đọc thêm các features khác ở trong docs nhé:
Validation
Deserialize
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
Serialize
from marshmallow import Schema, fields
class CustomerSchema[Schema]:
username = fields.Str[]
email = fields.Email[]
created = fields.DateTime[]
Ngoài ra, các bạn có thể đọc thêm các features khác ở trong docs nhé:
input_data = {'username': 'minhhahao', 'email': ''}
result = CustomerSchema[].load[input_data]
print[result.data]
Đầu tiên, mình sẽ khởi tạo một object model:
{'email': '', 'username': 'minhhahao'}
Tiếp theo, mình tạo một schema validate các field tương ứng trong objects models trên.
Để validate input data, ta sẽ sử dụng syntax:
from marshmallow import Schema, fields
class CustomerSchema[Schema]:
username = fields.Str[]
email = fields.Email[]
created = fields.DateTime[]
1. Cụ thể:input_data = {'username': 'minhhahao', 'email': 'abc'}
result = CustomerSchema[].load[input_data]
print[result.data]
Kết quả có được:
{'username': 'minhhahao'}
Tức là dữ liệu này đúng format mình mong muốn.
Thử một example khác
from marshmallow import Schema, fields
class CustomerSchema[Schema]:
username = fields.Str[]
email = fields.Email[]
created = fields.DateTime[]
class Meta:
strict=True
Kết quả:
In [21]: input_data = {'username': 'minhhahao', 'email': 'abc'}
...: result = CustomerSchema[].load[input_data]
...: print[result.data]
---------------------------------------------------------------------------
ValidationError Traceback [most recent call last]
in
1 input_data = {'username': 'minhhahao', 'email': 'abc'}
----> 2 result = CustomerSchema[].load[input_data]
3 print[result.data]
~/.pyenv/versions/3.6.5/envs/uiza-env3/lib/python3.6/site-packages/marshmallow/schema.py in load[self, data, many, partial]
595 .. versionadded:: 1.0.0
596 """
--> 597 result, errors = self._do_load[data, many, partial=partial, postprocess=True]
598 return UnmarshalResult[data=result, errors=errors]
599
~/.pyenv/versions/3.6.5/envs/uiza-env3/lib/python3.6/site-packages/marshmallow/schema.py in _do_load[self, data, many, partial, postprocess]
718 self.handle_error[exc, data]
719 if self.strict:
--> 720 raise exc
721
722 return result, errors
ValidationError: {'email': ['Not a valid email address.']}
Kết quả này là do value của email đang lỗi định dạng email:
from marshmallow import Schema, fields
class CustomerSchema[Schema]:
username = fields.Str[]
email = fields.Email[]
created = fields.DateTime[]
2. Vậy các bạn thắc mắc, làm sao để raise ra được lỗi ?In [25]: from marshmallow import ValidationError
...:
...: try:
...: input_data = {'username': 'minhhahao', 'email': 'abc'}
...: result = CustomerSchema[].load[input_data]
...: print[result.data]
...: except ValidationError as e:
...: print[e.messages]
...:
{'email': ['Not a valid email address.']}
Ok, ta quay về chỗ định nghĩa Schema, thêm option
from marshmallow import Schema, fields
class CustomerSchema[Schema]:
username = fields.Str[]
email = fields.Email[]
created = fields.DateTime[]
3:from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
0Thử lại example trên, ta sẽ thấy lỗi in ra:
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
1Để handle exception này, ta sẽ làm như sau:
Tiếp theo, trong Object Customer, ta mong muốn username là required. Trong Schema ta cần chỉnh lại như sau:
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
2Kiểm tra lại nào:
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
3Look good :v.
Kế tiếp, username ta mong muốn độ dài lớn hơn 8 ký tự và nhỏ hơn 16 ký tự.
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
4Kế quả sẽ là:
- Vậy, nếu bài toán của mình input data thừa ra các field thì sao. Mặc định, marshmallow sẽ remove những field đó ra. Tuy nhiên, ta có thể handle nó.
- Tuy nhiên bạn phải upgrade version của marshmallow lên bản 3.0: //marshmallow.readthedocs.io/en/3.0/upgrading.html
- Trong đó:
Deserialize
Serialize
Example:
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
5Ngoài ra, các bạn có thể đọc thêm các features khác ở trong docs nhé:
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
6Serialize
Ngoài ra, các bạn có thể đọc thêm các features khác ở trong docs nhé:
Example:
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
7Đầu tiên, mình sẽ khởi tạo một object model:
from datetime import datetime
class Customer[object]:
def __init__[self, username, email]:
self.username = username
self.email = email
self.created = datetime.now[]
8Tiếp theo, mình tạo một schema validate các field tương ứng trong objects models trên.