Kahibaro
Discord Login Register

مسیرها و قالب‌ها (Templates)

درک مسیرها (Routes) در Flask

در فصل «آشنایی با Flask» دیدی که چطور یک وب‌سرور ساده می‌سازیم. این‌جا تمرکز ما روی دو چیز است:

مسیر (Route) یعنی چه؟

هر بار که در مرورگر آدرسی مثل:

را می‌زنی، Flask باید بداند برای هر آدرس، چه کدی را اجرا کند و چه پاسخی برگرداند. این نگاشت «آدرس → تابع» همان چیزی است که با route می‌سازیم.

در Flask، برای تعریف یک مسیر از «دکوراتور» @app.route() استفاده می‌کنیم:

from flask import Flask
app = Flask(__name__)
@app.route("/")
def 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 "تماس با ما"

حالا:

مسیرهای پویا (Dynamic Routes)

گاهی بخشی از مسیر، ثابت نیست؛ مثلاً صفحهٔ پروفایل کاربران:

به‌جای ساختن ده‌ها مسیر جدا، از مسیر پویا استفاده می‌کنیم:

from flask import Flask
app = Flask(__name__)
@app.route("/user/<username>")
def show_user(username):
    return f"پروفایل کاربر: {username}"

مشخص کردن نوع متغیر مسیر

می‌توانی نوع دادهٔ متغیر مسیر را هم مشخص کنی:

مثال:

@app.route("/post/<int:post_id>")
def show_post(post_id):
    return f"نمایش پست با شناسهٔ {post_id}"

اگر کاربر برود روی /post/12post_id = 12 (عدد صحیح)

اگر برود روی /post/salam → خطای 404، چون salam عدد نیست.

مسیرهای با چند متغیر

می‌توانی چند متغیر را کنار هم در مسیر قرار دهی:

@app.route("/product/<category>/<int:item_id>")
def product_detail(category, item_id):
    return f"دسته: {category} | شناسه: {item_id}"

آدرس‌هایی مثل:

را پشتیبانی می‌کند.

متدهای 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>
    """

مشکل‌ها:

برای حل این مشکل از قالب‌ها (Templates) استفاده می‌کنیم.

ساختار پوشهٔ قالب‌ها

Flask به‌طور پیش‌فرض به دنبال فایل‌های قالب، در پوشه‌ای به نام templates می‌گردد.

پروژهٔ سادهٔ Flask معمولاً این‌طور است:

my_app/
    app.py
    templates/
        index.html
        about.html
        user.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)

در اینجا:

در فایل 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>

حالا:

ارسال لیست و دیکشنری به قالب

می‌توانی ساختارهای دادهٔ پایتون (مثل لیست و دیکشنری) را هم بفرستی:

@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>

نکات جدید:

مثال با دیکشنری:

@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>

اگر بعداً مسیر about را عوض کنی (مثلاً /about-us)، فقط کافی است در route تغییر دهی؛ قالب‌ها خودشان به‌روز می‌شوند.

خلاصهٔ عملی این فصل

در این فصل یاد گرفتی:

در فصل بعدی، روی «پردازش ورودی کاربر (فرم‌ها)» کار می‌کنیم و می‌بینی چطور دادهٔ ارسال‌شده از فرم‌ها را در مسیرها بگیری و در قالب‌ها نمایش دهی.

Views: 6

Comments

Please login to add a comment.

Don't have an account? Register now!