
فلسک یک فریمورک وب مبتنی بر پایتون است برای ایجاد سریع و ساده وبسرور که توسط آرمینروناچر توسعه دادهشده است. تلاش برای سادهنگه داشتن طراحی فلسک و کوچکی فریمورک و قائل نشدن بسیاری از پیشفرض ها برای برنامهنویسان دلیلیاست که این بستهنرم افزار را یک میکروفریمورک مینامند. فلسک رایگان و متنباز بوده و با مجوز آزاد BSD منتشر شده است.
کار با فلسک به قدری ساده است که اگر کمی با زبان پایتون آشنا باشید با دیدن اولین کدهای فلسک با ساختار این فریمورک آشنا میشوید. فریمورک فلسک با همهی سادگی خود بسیار قدرتمند و کاراست و به هیچ عنوان کوچک بودن فریمورک را نمیتوان با ضعیف بودن آن برابر دانست و امکانات فریمورکهای بزرگی مثل جنگو و ریلز را با اندکی جستوجو به دست میدهد. برای مثال از سرویسهای بزرگی که از فلسک استفاده میکنند میتوان از Pinterest و Linkedin نام برد که به مناسب بودن فلسک برای توسعهی سرویسهای اینترنتی اشاره دارد.
دو کتابخانهی اساسی پایههای قدرتمند فلسک را ساختهاند؛ به عنوان واسط وبسرور (WSGI) از کتابخانهی werkzeug و برای تمپلیتانجین از Jinja2 استفاده کرده اند که هردو کتابخانه توسط تیم توسعه ی فلسک توسعه یافته شده است.
بطور پیشفرض برای کار با دیتابیسها، اعتبارسنجی فرم ها و کاربران و از این دست کارها ابزار مشخصی در فلسک تعریف نشده است و میتوان از ابزارهای شخص ثالث (Third party applications) که برای آن توسعه داده شدهاند استفاده کرد.
برای نصب و راهانداری پروژهها معقول است یک محیط مجازی توسعه ساخت تا در حین کار و حتی یادگیری، مفسر عمومی و پکیجهای عمومی سیستم دچار تغییر و کانفلیکت نشوند. محیطهای توسعهمجازی یک کپی از مفسر پایتون را بصورت خصوصی در دایرکتوری پروژه شما ایجاد میکنند و بعد از فعال کردن این مفسر پکیجها هم بصورت خصوصی در دایرکتوری پروژه نصب میشوند.
نحوه ایجاد و فعالسازی محیط مجازی را از اینجا بخوانید:
حالا نوبت نصب بستهی فلسک است؛ متداول ترین روش نصب بستههای پایتون استفاده از مدیر بستهی pip است که با استفاده از آن فلسک با دستور زیر نصب میشود :
pip install flask
برای بررسی صحت نصب فلسک مفسر پایتون را بصورت تعاملی در ترمینال باز کنید (تنها دستور python را نوشته و enter کنید) و بستهی فلسک را با دستور زیر فراخوانی کنید :
import flask
اگر خطایی رخ نداد فلسک درست نصب شده است و میتوانید با اجرای دستور زیر نسخه نصب شده را بررسی کنید:
flask.__version__
فلسک هیچ محدودیتی درمورد ساختاربندی فایلهای پروژه برای شما ایجاد نمیکند و میتوانید ساختار خودتان را داشته باشید یا از روشهای متداول جامعهی فلسک استفاده کنید.
کدهای یک اپلیکیشن سادهی فلسک که عبارت Hello World را در یک صفحه ی وب نمایان میکند بصورت زیر است :
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run()
این برنامه از چند بخش تشکیل شده است : فراخوانی و تعریف فلسک، تعریف مسیرها، اجرای فلسک.
برای ساخت برنامههای فلسک، نیاز است تا ابتدا فلسک را در فایل پایتون خود import کنید و سپس یک نمونه (instance) از Flask بسازید. یعنی این بخش:
from flask import Flask app = Flask(__name__)
تنها آرگومان مورد نیاز برای کانستراکتور کلاس فلسک، نام ماژول یا پکیج main است که برای بیشتر برنامه ها `__name__` در پایتون مقدار درستی است.
میتوانیم برای نام اینستنس فلسک (در مثال بالا app)، از هر نام متغیر معتبری استفاده کنیم.
فلسک روی pip یک بسته از ماژولهای مرتبط به هم است و نه یک ماژول و به همین دلیل هر ماژول باید از درون بسته ی flask جداگانه ایمپورت بشود.
مسیرها همان آدرسهای (url های) مختلفی هستند که عملیاتهای متفاوتی بر اساس آنها انجام میشود. مثلا site.domain مسیر ریشه و site.domain/subdomain یک مسیر دیگر در همان سایت تعریف میکند. در کد مثال ما مسیر بصورت زیر تعریف شده بود :
@app.route('/') def hello_world(): return 'Hello World!'
در اینجا یک دکوریتور (decorator) از نوع ()route از app (که در قسمت قبل ساختیم) برای تابع Hello world تعریف کرده و آدرس مسیر ('/') را به آن بفرستید. مسیرها در فلسک اساس ساخت برنامهها هستند. با استفاده از مسیرها میتوانید به سادگی بخشهای مختلف وباپلیکیشن خود را بسازید و مدیریت کنید.
در آخر به پایتون میگوییم که فلسک را روی یک وبسرور اجرا کند که دستورات آن بصورت زیر است :
if __name__ == '__main__': app.run()
این شرط برای بررسی این موضوع است که آیا این فایل پایتون مستقیما اجرا میشود (برقراری شرط) و یا به عنوان یک ماژول در یک برنامه دیگر وارد شده است (عدم برقراری شرط).
این کد را در یک فایل مانند app.py ذخیره کرده و در خط فرمان با دستور python app.py اجرا کنید. خروجی روی ترمینال چیزی شبیه این است:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
که آدرس 127.0.0.1:5000 را که در خروجی مشخص شده است اگر در مرورگر خود باز کنید روی صفحه عبارت Hello World به صورت زیر نمایان میشود، (فلسک به صورت پیشفرض پورت ۵۰۰۰ را برای اجرا در نظر میگیرد):

تابع run میتواند پارامتر ای با عنوان host داشته باشد که مشخص میکند سرور برروی چه آدرسی اجرا شود، همچنین توسط پارامتر port میتوان پورتی که سرور روی آن اجرا شود را مشخص کرد و توسط پارامتر debug و دادن مقدار true به آن میتوان مشخص کرد که لاگها و گزارشات مربوط به اشکال یابی برنامه نیز چاپ شوند.
app.run(host='0.0.0.0', port=8080, debug=True)
برای اینکه سرور از طریق کامپیوترهای متصل به همین شبکه قابل مشاهده و استفاده باشد به پارامتر host مقدار 0.0.0.0 را میدهیم.
توجه کنید که پارامتر host از جنس string، پارامتر port از جنس integer و پارامتر debug از جنس boolean است.
در تعریف قوانین آدرسدهی میتوان به آدرسها با استفاده از عملگرهای <> متغیر اضافه کرد مانند <variable_name> تا بخشی از آدرس به صورت متغیر توسط تابع در دسترس باشد. همچنین میتوان نوع متغیر را با استفاده از یک مبدل مانند <converter:variable_name> مشخص کرد:
from flask import Flask app = Flask(__name__) @app.route('/user/<username>') def show_user_profile(username): # show the user profile for that user return (f'User {username}') @app.route('/post/<int:post_id>') def show_post(post_id): # show the post with the given id, the id is an integer return (f'Post {post_id}') @app.route('/path/<path:subpath>') def show_subpath(subpath): # show the subpath after /path/ return (f'Subpath {subpath}') app.run()
نوع پیشفرص برای متغیرها string است، اما همانطور که مشاهده میکنید انواع integer و path (مسیر) را نیز میتوانید استفاده کنید.
به نحوه آدرس دهی در برنامه زیر دقت کنید:
@app.route('/projects/') def projects(): return 'The project page' @app.route('/about') def about(): return 'The about page'
آدرس تعریف شده برای projects شبیه آدرس دایرکتوی است و در انتهای خود یک '/' دارد. اگر به این آدرس بدون '/' برویم فلسک ما را به آدرس اصلی (آدرس با '/') هدایت میکند.
آدرس تعریف شده برای about شبیه آدرس فایل است و در انتهای خود '/' ندارد. اگر به این آدرس با '/' برویم با خطای ۴۰۴ (صفحهای یافت نشد) مواجه خواهیم شد. این امر این امکان را میدهد تا آدرسهای تعریف شده به این سبک منحصر به فرد بوده و کمک میکند موتورهای جستوجو یک صفحه را دوبار ایندکس نکنند.
برنامهها هنگام دسترسی به آدرسها از متدهای HTTP مختلفی استفاده میکنند. به صورت پیشفرض یک آدرس تنها به متد GET پاسخ میدهد، اما با مشخص کردن متدهای لازم در پارامتر methods از دکوریتور ()route میتوان به متدهای مختلف پاسخ داد:
from flask import request @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': return do_the_login() else: return show_the_login_form()
در کد با بررسی نوع (method) درخواست (request) عملیات متفاوتی انجام میشود. این بدین معنی است که میتوانیم در یک آدرس یکسان، پاسخهای متفاوتی بنا بر متد درخواست که GET باشد یا POST بدهیم.
فلسک این امکان را میدهد تا با دریافت ریکوئست در یک آدرس، یک صفحه HTML رندر شده و به نمایش درآید. برای اینکار فلسک از فولدربندی خاصی استفاده میکند. در فولدر پروژه باید دو دایرکتوری به نام های static و templates ایجاد کنید که در دایرکتوری templates فایل های html و در دایرکتوری static فایلهای css و js خودتون رو قرار بدهید. سپس با استفاده از تابع render_template میتوانیم مشخص کنیم کدام یک از فایلهای داخل دایرکتوری templates رندر شده و به نمایش در بیاید. به برنامه زیر توجه کنید:
from flask import Flask, render_template app = Flask(__name__) @app.route("/") def index(): return "Hello World !" @app.route("/welcome") def welcome(): return render_template('welcome.html') if __name__ == __main__: app.run()
اگر کاربر به صفحه welcome/ برود فانکشن به جای متن خالی، نتیجه رندر فایل HTML را return میکند. توجه داشته باشید که این فایل HTML باید داخل پوشه templates قرار گرفته باشد تا فلسک آن را شناسایی بکند.
از آنجایی که فلسک تنها به عنوان دکوریتور برای توابعی که خود مشخص میکنیم قرار میگیرد و آنها را به آدرسهای مشخص شده مرتبط میکند، میتوان از آن در یک برنامه در کنار دیگر توابع استفاده کرد و نیازی به جدا سازی فایل مربوط به serve و اجرای برنامه از فایلی که عملیات برنامه در آن پیادهسازی شده نیست. به عنوان مثال به فایل زیر توجه کنید:
import keras import flask app = flask.Flask(__name__) def load_model() ... loads model def prepare_image(): ... proccess image for prediction return image @app.route("/predict", methods=["POST"]) def predict(): if flask.request.method == "POST": if flask.request.files.get("image"): ... gets image and call prepare_image() and do predict return flask.jsonify(data) if __name__ == "__main__": load_model() app.run()
این برنامه یک برنامه فلسک برای پیشبینی نتایج یک مدل یادگیریماشین است که عکس ارسالی به endpoint با آدرس predict/ و متد POST را آپلود کرده و با predict آن نتیجه را برمیگرداند. با اجرای کد، مدل مربوطه لود شده و سرور شروع به گوش دادن به endpoint ذکر شده برای دریافت درخواستها میکند و در صورت دریافت درخواستی حاوی تصویر، توابع مربوطه برای predict عکس را صدا زده و نتیجه را برمیگرداند.
نکته این برنامه در این است که توابعی در آن استفاده شده که توسط فلسک مدیریت نشده و به هیچ endpointای مرتبط نیستند و این توابع تنها یکبار هنگام اجرای برنامه صدا زده شده و عملیاتهای initialization را انجام میدهند.
فلسک یک فریمورک بسیار توسعهپذیر و متنباز است و میتوانید بصورت ماژولار کدهای آن را تقسیم بندی و استفاده کنید. همچنین پلاگینهای بسیاری هماکنون برای آن نوشته شده است که میتوانید در صفحهی extension های فلسک تعدادی از بهترین افزونههای فلسک را بیابید و استفاده کنید.
مقاله «میکروفریمورک فلسک - معرفی» از سایت کدرز
مقاله «آشنایی با میکرو-فریمورک فلسک» از سایت هایو
سری آموزش «The Flask Mega-Tutorial» از miguelgrinberg
کتاب Flask Web Development از انتشارات OReilly
این پست پیش از این در تیر ۹۷ در وبلاگ بینایی ماشین منتشر شده بود.