کتابخانه marshmallow در پایتون
marshmallow یک کتابخانهٔ محبوب برای سریالایز (serialize)، دیسریالایز (deserialize) و اعتبارسنجی (validation) دادهها در پایتون است. این کتابخانه بهویژه در ساخت APIها، تبدیل دادهها بین فرمتهای مختلف (مثل dict و JSON) و اتصال دادهها به مدلهای ORM کاربرد زیادی دارد.
چرا marshmallow؟
- نوشتن اسکیماها بهصورت کد پایتون که خوانا و قابل تست باشند.
- ادغام ساده با فریمورکهایی مانند Flask و با افزونههایی مثل marshmallow-sqlalchemy.
- پشتیبانی از فیلدهای مختلف، اعتبارسنجی، و هوکهای پیشپردازش و پسپردازش.
نصب
pip install marshmallow
# برای کار با SQLAlchemy:
pip install marshmallow-sqlalchemy
نصب ساده است. اگر از ORM استفاده میکنید، افزونهٔ مرتبط را هم نصب کنید تا تبدیل بین مدلهای ORM و اسکیماها راحتتر شود.
مفاهیم پایه
- Schema: تعریف ساختار دادهها و قوانین اعتبارسنجی.
- Fields: انواع فیلدها مثل fields.String، fields.Int، fields.DateTime و …
- load: تبدیل ورودی (مثلاً dict) به آبجکت پایتون یا dict پردازششده و اعتبارسنجی آن.
- dump: سریالایز کردن آبجکت پایتون به dict مناسب برای JSON یا ذخیرهسازی.
مثال ساده
from marshmallow import Schema, fields, ValidationError
class UserSchema(Schema):
id = fields.Int(required=True)
name = fields.Str(required=True)
email = fields.Email()
schema = UserSchema()
input_data = {"id": 1, "name": "Ali", "email": "ali@example.com"}
# Deserialize & validate
result = schema.load(input_data)
# Serialize
json_data = schema.dump(result)در این مثال یک اسکیما برای کاربر تعریف شده است. متد load ورودی را اعتبارسنجی میکند و در صورت خطا استثناء ValidationError پرتاب میشود. متد dump هم دادهها را برای ارسال به کلاینت یا ذخیرهسازی آماده میکند.
دستهبندی خروجی و مدیریت خطا
from marshmallow import ValidationError
try:
data = schema.load({"id": "not-a-number", "name": "Ali"})
except ValidationError as err:
print(err.messages) # {'id': ['Not a valid integer.']}در صورت خطای اعتبارسنجی، پیامهای واضحی دریافت میکنید که میتوانند مستقیماً به پاسخ API اضافه شوند.
فیلدهای متداول و گزینهها
- required: تعیین اجباری بودن فیلد
- default / missing: مقدار پیشفرض برای dump و load
- validate: پذیرش تابع یا callable برای اعتبارسنجی سفارشی
- allow_none: اجازهٔ مقدار None
Nested و لیستها
class AddressSchema(Schema):
street = fields.Str()
city = fields.Str()
class UserSchema(Schema):
name = fields.Str()
addresses = fields.List(fields.Nested(AddressSchema))
user = {
"name": "Sara",
"addresses": [{"street": "Valiasr", "city": "Tehran"}]
}
schema = UserSchema()
print(schema.load(user))در این مثال از Nested برای مدلسازی روابط یکبهچند استفاده شده است. marshmallow بهخوبی دادههای تو در تو را پردازش و اعتبارسنجی میکند.
هوکها: pre_load و post_load
from marshmallow import pre_load, post_load
class UserSchema(Schema):
name = fields.Str()
age = fields.Int()
@pre_load
def strip_name(self, data, **kwargs):
if 'name' in data:
data['name'] = data['name'].strip()
return data
@post_load
def make_user(self, data, **kwargs):
return User(**data) # تبدیل dict به آبجکت کاربردیهوکهای pre_load و post_load برای تغییر یا تبدیل دادهها قبل یا بعد از اعتبارسنجی مناسباند. در مثال بالا نام را پاکسازی میکنیم و سپس یک نمونهٔ کلاس User میسازیم.
سفارشیسازی اعتبارسنجی
from marshmallow import validates, ValidationError
class ProductSchema(Schema):
name = fields.Str(required=True)
price = fields.Float(required=True)
@validates('price')
def validate_price(self, value):
if value <= 0:
raise ValidationError('price must be positive')میتوانید اعتبارسنجی فیلد را با دکوراتور @validates انجام دهید یا از آرگومان validate هنگام تعریف فیلد استفاده کنید.
تنظیم رفتار برای فیلدهای ناشناخته
| تنظیم | توضیح |
|---|---|
| unknown=RAISE | ارزشیابی خطا برای فیلدهای ناشناخته |
| unknown=EXCLUDE | نادیده گرفتن فیلدهای اضافی |
| unknown=INCLUDE | شامل کردن فیلدهای اضافه در خروجی |
با تعریف Meta در اسکیما میتوانید نحوهٔ برخورد با فیلدهای اضافه را کنترل کنید.
مثال: استفاده در Flask و SQLAlchemy
# نمونهٔ سادهٔ ادغام با Flask
from flask import Flask, request, jsonify
from marshmallow import Schema, fields, ValidationError
app = Flask(__name__)
class PostSchema(Schema):
title = fields.Str(required=True)
content = fields.Str()
schema = PostSchema()
@app.route('/posts', methods=['POST'])
def create_post():
try:
data = schema.load(request.json)
except ValidationError as err:
return jsonify(err.messages), 400
# ذخیرهسازی مدل در DB
return jsonify(schema.dump(data)), 201در برنامههای واقعی بهتر است از marshmallow-sqlalchemy برای تبدیل مستقیم مدلهای SQLAlchemy به اسکیماها استفاده کنید تا نگهداری کد سادهتر شود.
نکات عملکرد و بهترین شیوهها
- برای حجم بالای دادهها از parameter
many=Trueهنگام لود/دامپ استفاده کنید تا پردازش دستهای بهینه باشد. - در صورت نیاز به سرعت بیشتر، از نسخههای سبکتر فیلدها یا تبدیلهای دستی (در بخشهای بحرانی) استفاده کنید.
- پیامهای خطا را ساختاربندی کنید تا در پاسخهای API قابل مصرف برای کلاینت باشند.
- اسکیماها را کوچک و متمرکز نگه دارید؛ از ارجاعهای Nested برای جلوگیری از تکرار استفاده کنید.
بهبود: نمونهٔ بهتر برای تبدیل به مدل SQLAlchemy
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
from models import User # مدل SQLAlchemy
class UserAutoSchema(SQLAlchemyAutoSchema):
class Meta:
model = User
load_instance = Trueاستفاده از کلاسهای اتوماتیک marshmallow-sqlalchemy باعث کاهش کد و هماهنگی بهتر بین مدل و اسکیما میشود. گزینهٔ load_instance=True باعث میشود که load مستقیماً یک نمونهٔ مدل برگرداند.
خلاصه و جمعبندی
marshmallow ابزاری قدرتمند و منعطف برای سریالایز و اعتبارسنجی دادهها در پایتون است. با استفاده از اسکیماها، فیلدها، هوکها و افزونههای مرتبط میتوان از آن در پروژههای کوچک تا سیستمهای بزرگ backend و API استفاده کرد. رعایت بهترین شیوهها مانند استفاده از nested، مدیریت خطاها و یکپارچهسازی با ORMها تجربهٔ توسعه را بهبود میبخشد.
در صورت نیاز میتوان مثالهای بیشتر مانند استفاده از marshmallow-dataclass، پردازش جریانهای بزرگ داده، یا سفارشیسازی پیامهای خطا را نیز ارائه کرد.
آیا این مطلب برای شما مفید بود ؟




