Table of Contents
درک مسیرها (Routes) در Flask
در فصل «آشنایی با Flask» دیدی که چطور یک وبسرور ساده میسازیم. اینجا تمرکز ما روی دو چیز است:
- مسیرها (Route)ها: آدرسهای مختلف سایت مثل
/،/about،/user/ali - قالبها (Templates): جدا کردن HTML از کد پایتون و ساختن صفحات پویا
مسیر (Route) یعنی چه؟
هر بار که در مرورگر آدرسی مثل:
http://localhost:5000/http://localhost:5000/abouthttp://localhost:5000/user/ali
را میزنی، Flask باید بداند برای هر آدرس، چه کدی را اجرا کند و چه پاسخی برگرداند. این نگاشت «آدرس → تابع» همان چیزی است که با route میسازیم.
در Flask، برای تعریف یک مسیر از «دکوراتور» @app.route() استفاده میکنیم:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "سلام، این صفحهٔ اصلی است!""/"مسیر صفحهٔ اصلی است (Root).- تابع
homeوقتی اجرا میشود که کاربر این مسیر را در مرورگر باز کند. - مقدار
returnهمان چیزی است که به مرورگر فرستاده میشود (در سادهترین حالت یک متن).
تعریف چند مسیر مختلف
میتوانی چند مسیر مختلف برای قسمتهای مختلف سایت تعریف کنی:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "صفحهٔ اصلی"
@app.route("/about")
def about():
return "دربارهٔ ما"
@app.route("/contact")
def contact():
return "تماس با ما"حالا:
http://localhost:5000/→ تابعindexhttp://localhost:5000/about→ تابعabouthttp://localhost:5000/contact→ تابعcontact
مسیرهای پویا (Dynamic Routes)
گاهی بخشی از مسیر، ثابت نیست؛ مثلاً صفحهٔ پروفایل کاربران:
/user/ali/user/sara/user/admin
بهجای ساختن دهها مسیر جدا، از مسیر پویا استفاده میکنیم:
from flask import Flask
app = Flask(__name__)
@app.route("/user/<username>")
def show_user(username):
return f"پروفایل کاربر: {username}"<username>یک «متغیر مسیر» است.- مقدار واقعی (مثل
aliیاsara) در آرگومان تابع (username) قرار میگیرد.
مشخص کردن نوع متغیر مسیر
میتوانی نوع دادهٔ متغیر مسیر را هم مشخص کنی:
<string:name>(پیشفرض)<int:id><float:price>
مثال:
@app.route("/post/<int:post_id>")
def show_post(post_id):
return f"نمایش پست با شناسهٔ {post_id}"
اگر کاربر برود روی /post/12 → post_id = 12 (عدد صحیح)
اگر برود روی /post/salam → خطای 404، چون salam عدد نیست.
مسیرهای با چند متغیر
میتوانی چند متغیر را کنار هم در مسیر قرار دهی:
@app.route("/product/<category>/<int:item_id>")
def product_detail(category, item_id):
return f"دسته: {category} | شناسه: {item_id}"آدرسهایی مثل:
/product/mobile/10/product/laptop/3
را پشتیبانی میکند.
متدهای HTTP (GET، POST و …)
در فصل «پردازش ورودی کاربر (فرمها)» بیشتر با متدها کار خواهیم کرد؛ اینجا فقط اشاره کوتاه:
به طور پیشفرض هر مسیر فقط متد GET را قبول میکند. اگر بخواهی متدهای دیگر مثل POST را هم بپذیری، در route مشخص میکنی:
from flask import Flask, request
app = Flask(__name__)
@app.route("/submit", methods=["GET", "POST"])
def submit():
if request.method == "POST":
return "دادهای دریافت شد (POST)"
else:
return "این صفحهٔ فرم است (GET)"چرا به قالبها (Templates) نیاز داریم؟
اگر بخواهی صفحات واقعی HTML بنویسی، دیگر برگرداندن صرف return "سلام" کافی نیست. فرض کن بخواهی HTML زیر را برگردانی:
@app.route("/")
def index():
return """
<html>
<head><title>سایت من</title></head>
<body>
<h1>سلام!</h1>
<p>به سایت من خوش آمدی</p>
</body>
</html>
"""مشکلها:
- کد HTML و پایتون قاطی شدهاند.
- اگر چند صفحه مشابه داشته باشی، کد تکرار میشود.
- ویرایش کردن سخت است.
برای حل این مشکل از قالبها (Templates) استفاده میکنیم.
ساختار پوشهٔ قالبها
Flask بهطور پیشفرض به دنبال فایلهای قالب، در پوشهای به نام templates میگردد.
پروژهٔ سادهٔ Flask معمولاً اینطور است:
my_app/
app.py
templates/
index.html
about.html
user.htmlapp.py→ کد پایتون و تعریف مسیرهاtemplates/→ فایلهای HTML (قالبها)
استفاده از `render_template`
برای استفاده از قالبها، تابع render_template را از Flask وارد میکنیم:
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
حالا Flask میرود سراغ پوشهٔ templates و فایل index.html را پیدا و به مرورگر ارسال میکند.
یک مثال کامل ساده
app.py:
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
return render_template("index.html")
@app.route("/about")
def about():
return render_template("about.html")
templates/index.html:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>صفحهٔ اصلی</title>
</head>
<body>
<h1>سلام!</h1>
<p>این صفحهٔ اصلی سایت است.</p>
<a href="/about">رفتن به صفحهٔ دربارهٔ ما</a>
</body>
</html>
templates/about.html:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>دربارهٔ ما</title>
</head>
<body>
<h1>دربارهٔ ما</h1>
<p>این یک متن نمونهٔ دربارهٔ ما است.</p>
<a href="/">بازگشت به خانه</a>
</body>
</html>ارسال داده از مسیر به قالب
قدرت اصلی قالبها زمانی دیده میشود که به آنها دادهٔ پویا بدهیم. مثلاً نمایش نام کاربر، لیست محصولات، پیام خوشآمدگویی و …
تابع render_template میتواند هر تعداد متغیر بگیرد و آنها را به قالب بفرستد:
@app.route("/hello")
def hello():
name = "علی"
age = 25
return render_template("hello.html", user_name=name, user_age=age)در اینجا:
user_nameوuser_ageنام متغیرهایی هستند که در قالب استفاده میکنیم.- مقدارشان از متغیرهای پایتونی
nameوageمیآید.
در فایل templates/hello.html میتوانیم این مقادیر را با سینتکس قالب Jinja2 استفاده کنیم:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>سلام</title>
</head>
<body>
<h1>سلام {{ user_name }}!</h1>
<p>سن شما: {{ user_age }}</p>
</body>
</html>{{ ... }}برای نمایش مقدار یک متغیر در قالب استفاده میشود.
مسیر پویا + قالب پویا
یک ترکیب معمول: مسیر پویا و قالب پویا با هم.
@app.route("/user/<username>")
def user_profile(username):
return render_template("user.html", username=username)
templates/user.html:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>پروفایل {{ username }}</title>
</head>
<body>
<h1>پروفایل {{ username }}</h1>
<p>به پروفایل {{ username }} خوش آمدید.</p>
<a href="/">بازگشت به صفحهٔ اصلی</a>
</body>
</html>حالا:
/user/ali→ صفحهای با عنوان و متنali/user/sara→ صفحهای باsara
ارسال لیست و دیکشنری به قالب
میتوانی ساختارهای دادهٔ پایتون (مثل لیست و دیکشنری) را هم بفرستی:
@app.route("/products")
def products():
items = ["موبایل", "لپتاپ", "تبلت"]
return render_template("products.html", products=items)
در templates/products.html:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>محصولات</title>
</head>
<body>
<h1>لیست محصولات</h1>
<ul>
{% for item in products %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>نکات جدید:
{% ... %}برای دستورات کنترلی (مثلfor،if) استفاده میشود.{{ ... }}همچنان برای نمایش مقدار متغیر است.
مثال با دیکشنری:
@app.route("/info")
def info():
user = {
"name": "نگار",
"age": 30,
"city": "تهران"
}
return render_template("info.html", user=user)
templates/info.html:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>اطلاعات کاربر</title>
</head>
<body>
<h1>اطلاعات کاربر</h1>
<p>نام: {{ user.name }}</p>
<p>سن: {{ user.age }}</p>
<p>شهر: {{ user.city }}</p>
</body>
</html>شرطها در قالبها (نمای کلی)
بدون رفتن به جزئیات عمیق، بد نیست بدانی که در قالبها میتوانی شرط هم بگذاری؛ مثلاً اگر کاربر وارد شده بود یک چیز نشان بده، اگر نه چیز دیگر.
@app.route("/dashboard")
def dashboard():
logged_in = False
return render_template("dashboard.html", logged_in=logged_in)
templates/dashboard.html:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>داشبورد</title>
</head>
<body>
<h1>داشبورد</h1>
{% if logged_in %}
<p>شما وارد شدهاید.</p>
{% else %}
<p>لطفاً وارد شوید.</p>
{% endif %}
</body>
</html>لینکدادن بین مسیرها با `url_for`
نوشتن آدرسها به صورت مستقیم مثل /about ممکن است بعداً مشکلساز شود (اگر مسیر را عوض کنی، باید همهجا تغییرش دهی). بهتر است در قالبها از تابع url_for استفاده کنی.
در پایتون:
from flask import Flask, render_template, url_for
app = Flask(__name__)
@app.route("/")
def home():
return render_template("nav.html")
@app.route("/about")
def about():
return "صفحهٔ دربارهٔ ما"
در templates/nav.html:
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="UTF-8">
<title>ناوبری</title>
</head>
<body>
<h1>ناوبری سایت</h1>
<ul>
<li><a href="{{ url_for('home') }}">خانه</a></li>
<li><a href="{{ url_for('about') }}">دربارهٔ ما</a></li>
</ul>
</body>
</html>url_for('home')آدرس تابعی با نامhomeرا میسازد (یعنی/).url_for('about')آدرس تابعaboutرا میسازد (یعنی/about).
اگر بعداً مسیر about را عوض کنی (مثلاً /about-us)، فقط کافی است در route تغییر دهی؛ قالبها خودشان بهروز میشوند.
خلاصهٔ عملی این فصل
در این فصل یاد گرفتی:
- چطور با
@app.route()مسیرهای مختلف برای سایت تعریف کنی. - چطور از مسیرهای پویا با
<variable>و<int:id>استفاده کنی. - چطور قالبها را در پوشهٔ
templatesقرار دهی. - چطور با
render_templateیک فایل HTML را برگردانی. - چطور متغیرها، لیستها و دیکشنریها را به قالبها بفرستی و با
{{ ... }}و{% ... %}استفاده کنی. - چطور با
url_forبه صورت امن بین مسیرها لینک بسازی.
در فصل بعدی، روی «پردازش ورودی کاربر (فرمها)» کار میکنیم و میبینی چطور دادهٔ ارسالشده از فرمها را در مسیرها بگیری و در قالبها نمایش دهی.