یادگیری فلاسک؛ ساختار برنامه در Flask - بخش دوم

فریم ورک Flask بسیار انعطاف پذیر و قابل اطمینان است و بهیچ وجه دچار دردسر یا سردرگمی نمیشه. همانطور که در بخش اول نشان دادم برای شروع فلاسک احتیاج به ساختار خاصی نیست و با حداقل دانش پایتون تونستیم خروجی لازم را نشان دهیم.


در این سری از یادگیری فلاسک نشان میدم چطور دایرکتوری‌ها و فایل‌ها را در فلاسک سازماندهی کنیم. یکی از مزایای فلاسک اینه که شما مجبور نیستید از ساختار از پیش تعریف شده استفاده کنید و کاملا ساختار پوشه‌ها و فایل‌ها به سلیقه شما بستگی دارد؛ در اینجا من از ساختاری که خودم از آن در ساخت سرویس‌های فلاسک استفاده میکنم را نشان میدهم. ( توجه داشته باشید این مجموعه آموزشی فلاسک تنها توسعه‌دهندگان مبتدی را هدف گرفته که تازه میخواهند وارد دنیای برنامه‌نویسی شوند - به این خاطر است که من فریم‌ورک Flask را برای شروع انتخاب کرده‌ایم؛ اما این دلیل نمیشود که فلاسک فریم‌ورک ناکارامد است و بین برنامه‌نویسان حرفه‌ای استفاده نمیشود، برعکس، سرویس‌های بسیاری همانند Netflix - Reddit - Airbnb - Mozilla - Uber از فلاسک استفاده میکنند).


«کُدنویسی تمیز و قابل فهم هنر است». این هنر یک شبه و با عجله حاصل نمیشود ولی اگر بدرستی راه درست را انتخاب کنید و با تمرین و تذکار این کار را انجام دهید قول میدهم بهترین باشید. درس اول برای هنرمند شدن «نوشتن کُد کم» است؛ این یعنی کُد شما باید بدور از پیچیدگی باشد و با کمترین کُد ممکن به نتیجه دلخواه برسید.


ساختار برنامه در فلاسک


اولین کاری که برای سازماندهی ساختار یک پروژه باید انجام دهیم، ماژولار نویسی کُد است. این یعنی چی؟ ماژولار نویسی یعنی هر بخش از کُد را طوری بنویسم که براحتی قابل ویرایش و قابل انتقال و مجزا باشد. در پایتون این کار را package میگویند؛ جایی که کُد نوشته می شود و به داخل برنامه فلاسک تزریق میشود که به import کردن پکیج مشهور است.

نوشتن کُد بطور ماژولار انعطاف پذیری بیشتر را به همراه دارد؛ تقسیم کردن منطق برنامه به چندین فایل میتواند توسعه دادن سرویس‌هایمان را راحتر و قابل خواندنی‌تر کند.

ما این کار را در این بخش انجام میدیم، تبدیل یک فایل برنامه (که قبلا در بخش اول دیدم) به چندین فایل و ماژولار کردن آنها.

در بخش اول با هم یک دایرکتوری flaskapp ایجاد و داخل آن فایل app.py را ایجاد کردیم. وقت آن است که ساختار برنامه را بصورت زیر عوض کنیم:

flaskapp
├── app
│   ├── __init__.py
│   └── views.py
├── app.py
├── .env
└── requirements.txt


هماطور که می‌بینید داخل دایرکتوری پروژه دایرکتوری با نام app که شامل فایل‌های init__.py__ و views.py است را درون آن درست کردیم. این دقیقا همان چیزی است که میخواهیم؛ این قرار است سرویس فلاسک ما باشد که به عنوان package تعریف کردیم.

کار را برا فایل init__.py__ شروع میکنیم و کُدهای زیر را در آن قرار میدهیم. توجه داشته باشید که بودن فایل init__.py__ برای داشتن پکیج ضروری است.

from flask import Flask

app = Flask(__name__)

from app import views


کار را برا فایل init__.py__ شروع میکنیم و کُدهای زیر را در آن قرار میدهیم. توجه داشته باشید که بودن فایل init__.py__  برای داشتن پکیج ضروری است.

init__.py__ تمام بخش‌های برنامه را در کنار هم در یک package نگاه می‌دارد و به مفسر پایتون میگوید که با آن به عنوان پکیج رفتار کند.

حال بیایید view برنامه را در فایل views.py اضافه کنیم:

from app import app

@app.route('/')
def index():
    return "Hello, World!"


همانند بخش اول یک view جدید با دکوراتور app.route@ تعریف و به آن آدرس URL میدهیم. تنها تفاوتی که با برنامه قبلی دارد خط اول است که from app import app را به آن اضافه کرده‌ایم.

خط اول در واقع متغیر app را که در دایرکتوری /app در فایل  init__.py__ درست کرده‌ایم را به فایل اضافه (import) میکند؛ این کار باعث میشود متغیر app از هرجای برنامه قابل دسترسی باشد.

حال شما میدونید چطور route در برنامه تعریف کنید. همانند کُد زیر بدلخواه route دیگر تعریف کنید:

from app import app

@app.route('/')
def index():
    return "Hello, World!"

@app.route('/about')
def about():
    return "About Page"

همانطور که حدس زده‌اید؛ route با آدرس about/ تعریف کردیم که هنگام مراجعه به این آدرس خروجی About Page از طریق تابع ()about نمایش داده میشود.

قبل از اینکه بتوانیم برنامه را اجرا کنیم، باید نقطه شروع برنامه را مشخص کنیم که به entrypoint معروف است.

entrypoint یا نقطه ورود جایی است که برنامه ما اجرا میشود.

به فایل app.py در ریشه دایرکتوری را بصورت زیر ویرایش کنید:

from app import app

if __name__ == "__main__":
    app.run()


در خط اول متغیر app را از پکیج app که تازه ایجاد کرده‌ایم را import میکند - آنگاه از متُد ()app.run برای اجرا برنامه استفاده مکنیم.

ولی قبل از اجرا برنامه باید متغیرهای FLASK_APP و FLASK_ENV را به برنامه اضافه کنیم - درست همان کاری که در بخش اول انجام دادیم با این تفاوت که متغیرها را در فایل env. قرار میدهیم که هر سری لازم نباشد در محیط shell آنها را وارد کنیم! فراموش نکنید که محیط مجازی شما باید روشن باشد.

$ source venv/bin/activate

فایل env. را با مقادیر زیر پُر کنید:

FLASK_APP=app.py
FLASK_ENV=development

برای اینکه برنامه فلاسک ما از وجود فایل env. باخبر باشد؛ باید پکیج python-dotenv را با pip نصب کنیم:

$ pip3 install python-dotenv


اجرای برنامه


همانند گذشته برنامه را با دستور flask run در ترمینال اجرا می کنیم:

$ flask run

این اجرا خروجی زیر را به همراه خواهد داشت:

* Serving Flask app "app.py" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 115-552-939

به آدرس /http://127.0.0.1:5000 در مرورگر بروید و خروجی‌ها ار همانند برنامه قبل مشاهده کنید. آدرس http://127.0.0.1:5000/about نیز خروجی About Page به همراه دارد. برای تست میتوانید چندین route دیگر به برنامه اضافه کنید.


requirements.txt


فایل requirements.txt در ریشه پروژه ما وجود دارد. این فایل تمام پکیج‌های لازم برای اجرای برنامه که از قبل نصب کرده‌ایم را در خود ذخیره میکند. 

تنها کافیست دستور زیر را در محیط مجازی که قبلا active کرده‌اید اجرا کنید:

$ pip3 freeze > requirements.txt

حال این فایل باید همانند مقادیر زیر را داشته باشد:

click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.3
MarkupSafe==1.1.1
pkg-resources==0.0.0
python-dotenv==0.15.0
Werkzeug==1.0.1


بعدها نیز برای نصب این پکیج‌ها از فایل requirements.txt دستور pip3 install -r requirements.txt لازم است.

$ pip3 install -r requirements.txt


«تبریک میگم» شما یاد گرفتید که چطور ساختار برنامه Flask به عنوان یک پکیج تغییر دهید.