carvanro
carvanro
خواندن ۳ دقیقه·۷ سال پیش

اعتبار سنجی در فلسک با cerberus ( نگهبان جهنم )

ما توی کاروانرو از سرویس های زیادی که با Flask (فلسک) راه اندازی شده و این سرویس ها از طریق JSON با هم در ارتباط هستند، برای اعتبار سنجی JSON ما از سربرس استفاده کردیم و این پست قرار که نشون بده که سربرس چطور کار میکنه و چطور توی API کاروانرو پیاده سازی شده.

با یک مثال ساده ابتدا شروع میکنیم

سربرس برای اعتبارسنجی به یک الگو(schema) نیاز داره.

Import Validator schema = {'name': {'type': 'string'}} v = Validator(schema)

و حالا میتونی از این الگویی که به سربرس دادیم استفاده کنیم.

>>> document = {'name': 1 } >>> v.validate(document) False >>> v.errors {'name': 'must be an string'}

ولی خب این مثال کمی ساده بنظر میرسه و توی دنیای واقعی کاربردی نداره.
برای روشن تر شدن قضیه بیایید اول به صفحه Login این رو اضافه کنیم.

# login_schema.py login_schema = { 'user_name': { 'type': 'string', 'required': True }, 'password': { 'type': 'string', 'required': True }, }
# view.login.py
from cerberus import Validator
@app.route('/login', methods=[ 'POST']) def login_user(): data = request.get_json() v = Validator(login_schema)
If v.validate(data): return jsonify({'status': 'ok'}) else: return jsonify(validator.errors), 422

خب بیاین یکم پایتونی تر باشیم و این اعتبارسنج رو به یک decorator تبدیلش کنیم

# validator_schema.py
from flask import jsonify, request
from functools import wraps
from cerberus import Validator
def validate_schema(schema): def contextualized_decorator(view_func): @wraps(view_func) def wrapper(*args, **kwargs): data = request.get_json() validator = Validator(schema) if not validator.validate(data): return jsonify(validator.errors), 422 return view_func(*args, **kwargs) return wrapper return contextualized_decorator

چرا از wraps استفاده شد؟

>>> from functools import wraps >>> def my_decorator(f): ... @wraps(f) ... def wrapper(*args, **kwds): ... print 'Calling decorated function' ... return f(*args, **kwds) ... return wrapper
>>> @my_decorator ... def example(): ... """Docstring""" ... print 'Called example function'
>>> example() Calling decorated function Called example function >>> example.__name__ 'example' >>> example.__doc__ 'Docstring'

؛ اگه از wraps استفاده نکنیم example.__name__ تبدیل میشه به wrapper که این خوب نیست و اسم متد اصلی حذف میشه و بعد در کامنت گذاری متدها مشکل بوجود میاره.

حالا دیگه ما decorator مون آماده بکار هست.

@app.route('/login', methods=[ 'POST']) @validate(login_schema) def login_user(): return jsonify({'status': 'ok'})
⋊> ~ curl -d '{"user_name":"carvanro", "password":"pass"}' \ -H "Content-Type: application/json" -X POST http://127.0.0.1:5000/login ⋊> ~ {'status': 'ok'}

در صورت دریافت JSON نامعتبر

⋊> ~ curl -d '{"user_name": 123, "password":"pass"}' \ -H "Content-Type: application/json" -X POST http://127.0.0.1:5000/login ⋊> ~ {'user_name': 'must be of string type'}

حالا کافیه این روش رو برای هرجایی که مایل باشید بکار ببرید اونم فقط با یک decorator و schema

برنامه نویسیپایتونفلسک
کاروانرو - پلتفرمی برای اشتراگ گذاری سفر
شاید از این پست‌ها خوشتان بیاید