تگ‌ها - Tags


تگ‌ها در جنگو ابزاری هستند برای افزودن منطق برنامه‌نویسی به قالب‌ها (Template) و نشان می‌دهند که در این بخش چیزی فراتر از HTML ساده وجود دارد. در واقع تگ‌ها به جنگو می‌گویند که دستورات خاصی را درون براکت‌های {% tag %} اجرا کند. جنگو مجموعه‌ای متنوع از ده‌ها تگ را فراهم کرده که به کمک آن‌ها می‌توان منطق‌های مختلف را در قالب‌ها پیاده‌سازی کرد. ساختار کلی همه تگ‌ها به صورت {% tag %} است.

  • برخی تگ‌ها متن یا محتوای مشخصی را در خروجی تولید می‌کنند.

  • برخی دیگر جریان نمایش را با استفاده از حلقه‌ها {% for %} یا شرط‌ها {% if %} کنترل می‌کنند.

  • دسته‌ای هم برای بارگذاری داده‌های خارجی در قالب به‌کار می‌روند تا در ادامه بتوان از آن‌ها توسط متغیرها استفاده کرد.

تگ Extends


تگ {% extends %} در جنگو برای ارث‌بری از یک تمپلیت پایه استفاده می‌شود. به بیان ساده، وقتی تمپلیتی از extends استفاده کند، یعنی محتوای آن بر اساس یک قالب والد (Parent Template) ساخته خواهد شد.

در این روش ابتدا یک تمپلیت اصلی (مثلاً base.html) تعریف می‌شود و سپس صفحات دیگر با استفاده از تگ extends محتوای خود را در بخش‌های مشخص‌شده به آن اضافه می‌کنند. به این ترتیب هر صفحه می‌تواند محتوای متفاوتی داشته باشد، اما همگی از ساختار اصلی یکسانی پیروی می‌کنند.

مزیت این کار این است که نیاز به تکرار کدها از بین می‌رود. به کمک extends می‌توان بارها از یک قالب پایه و حتی متغیرهای آن استفاده کرد و فقط بخش‌های متغیر را در هر صفحه تغییر داد.

{% extends 'base.html' %}

 
تگ {% extends %} یک آرگومان ورودی می‌گیرد که نام تمپلیت والد (Parent Template) است. وقتی یک تمپلیت فرزند که از extends استفاده می‌کند، رندر می‌شود، جنگو ابتدا تمپلیت والد را به‌عنوان یک اسکلت اصلی بارگذاری می‌کند و سپس محتوای فرزند را طبق بلوک‌های تعریف‌شده با {% block %} ... {% endblock %} در جای مناسب قرار می‌دهد.

تگ {% extends %} باید اولین تگ در تمپلیت باشد (قبل از هر تگ دیگری، حتی تگ‌های بارگذاری مثل {% load %}). در غیر این صورت، جنگو آن را نادیده می‌گیرد و ارث‌بری انجام نخواهد شد.

تگ Block


تگ {% block %} همراه با {% endblock %} برای مشخص کردن بخش‌های قابل تغییر در یک تمپلیت والد استفاده می‌شود. وقتی یک تمپلیت پایه (Base Template) ساخته می‌شود، بخش‌هایی که قرار است توسط تمپلیت‌های فرزند تغییر کنند یا مقدار جدید بگیرند داخل بلاک‌ها قرار می‌گیرند. سپس در تمپلیت فرزند، می‌توان همان بلاک‌ها را بازنویسی (override) کرد و محتوای دلخواه را جایگزین آن‌ها نمود. به این ترتیب ساختار کلی صفحه ثابت می‌ماند، اما محتوای بخش‌های خاص در هر صفحه می‌تواند متفاوت باشد.

{% block blockname %}
    Block Content
{% endblock blockname %}

 

━◦○◦ نکته‌های مهم ◦○◦━

  • باید توجه داشت که blockname نام بلاک بوده و باید یکتا باشد.
  • ‼ می‌توان چندین بلاک مختلف در یک تمپلیت والد تعریف کرد.
  • ‼ بلاک‌ها قابلیت تو در تو (nested) ندارند.
  • ‼ اگر تمپلیت فرزند بلاکی را بازنویسی نکند، همان محتوای پیش‌فرض داخل بلاک تمپلیت پایه نمایش داده می‌شود.
  • ‼ برای استفاده از محتوای قبلی یک بلاک همراه با محتوای جدید، می‌توان از کلمه کلیدی {{ block.super }} در بلاک فرزند استفاده کرد

tutorial/templates/base.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> {% block title %} Araz.S.X {% endblock title %} </title>
    {% block style %}{% endblock style %}
  </head>
  <body>
    {% block content %}{% endblock content %}
    {% block script %}{% endblock script %}
  </body>
</html>

 

در فایل base.html با استفاده از تگ {% block %} مشخص می‌کنیم که در این بخش فضایی وجود دارد تا قالب‌های فرزند، هنگام ارث‌بری از base.html، محتوای مربوط به همان بلوک (blockname) را در آن قرار دهند. به طور معمول، در این فایل می‌توان یک بلوک برای عنوان صفحه (مانند block title) و یک بلوک دیگر برای محتوای اصلی (مانند block content) تعریف کرد. قالب‌های فرزند هنگام ارث‌بری از base.html، محتوای مورد نیاز خود را در این بلوک‌ها قرار می‌دهند. برای مثال، عنوان صفحه در تگ title به کمک block title بازنویسی می‌شود و محتوای متغیر هر صفحه در ناحیه‌ی block content درج خواهد شد. با این کار ساختار کلی سایت، شامل بخش‌های مشترکی مثل هدر یا توضیحات ثابت، یکسان باقی می‌ماند، اما بخش‌های خاص هر صفحه به‌طور مستقل قابل سفارشی‌سازی است. این روش علاوه بر جلوگیری از تکرار کد، باعث نظم و انعطاف‌پذیری بیشتر در مدیریت قالب‌ها می‌شود.

اکنون یک قالب برای صفحه اصلی ایجاد می‌کنیم که ساختار کلی خود را از فایل base.html به ارث می‌برد و تنها بخش محتوای مخصوص به خودش را جایگزین می‌کند. با {% extends "base.html" %} اعلام می‌کنیم که این قالب فرزند است و از ساختار base.html استفاده می‌کند. در بلوک title، مقدار پیش‌فرض عنوان (یعنی همان block.super) حفظ شده و عبارت Home به آن اضافه شده و در نهایت در بلوک content، محتوای اختصاصی صفحه اصلی نوشته شده که هنگام رندر جایگزین بخش مربوطه در قالب پایه می‌شود.

coreapp/templates/home.html

{% extends "base.html" %}
{% block title %} {{ block.super }} | Home  {% endblock title %} 
{% block content %}
  <h1> Tutorial Home Page </h1>
  <p> page is rendered from <b>"base.html"</b> as BASE & <b>"home.html"</b> as CONTENT Templates </p>
{% endblock content %}

 

حال کافیست با جایگزین کردن 'home.html' به جای 'base.html' در تابع homeFunc() در views.py به نمایش زیر در رابط کاربری دست یابیم

تگ Include


تگ {% include %} برای بارگذاری و نمایش یک تمپلیت دیگر در داخل تمپلیت جاری استفاده می‌شود. به بیان ساده، این تگ مثل یک «کپی‌پیست هوشمند» عمل می‌کند و باعث می‌شود قطعات تکراری کد (مثل footer ،navbar یا sidebar) را فقط یک بار تعریف کنیم و در چندین صفحه‌ی مختلف استفاده کنیم.

{% include 'template.html' %}

برای نمونه ساختار ساده‌ای برای تمپلیت‌های navbar و footer در ردیف تمپلیت‌های پایه ایجاد می‌کنیم.

tutoriaL/templates/navbar.html

<nav>
  <h1>ARAZ. S. X. LOGO</h1>
  <hr>
</nav>

tutoriaL/templates/footer.html

<footer>
  <hr>
  <small>Copyright © 2025</small>
</footer>

حال می‌توان، تمپلیت‌ها را به ساختار تمپلیت پایه base با بهره‌گیری از تگ include اضافه نمود

tutorial/templates/base.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> {% block title %} Araz.S.X {% endblock title %} </title>
    {% block style %}{% endblock style %}
  </head>
  <body>
    
    {% include "navbar.html" %}     <!-- NAVBAR TEMPLATE -->
    {% block content %}{% endblock content %}
    {% include "footer.html" %}     <!-- FOOTER TEMPLATE -->

    {% block script %}{% endblock script %}
  </body>
</html>

صفحه Home به شکل زیر نمایش داده خواهد شد

 

━◦○◦ نکته‌های مهم ◦○◦━

  • ‼ می‌توان متغیرها را هم به تمپلیت include شده ارسال کرد.
{% include "sidebar.html" with section=posts %}

در این حالت متغیر section با محتوای داده‌های posts در فایل sidebar.html در دسترس خواهد بود.

  • ‼ گر فایل تمپلیت وجود نداشته باشد، می‌توان با عبارت ignore missing از بروز خطا جلوگیری کرد. 
{% include "optional.html" ignore missing %}
 
  • ‼ بهترین استفاده از include برای بخش‌های تکراری و کوچک است (مثل هدر، فوتر، فرم ورود و ...). برای ساختارهای بزرگ‌تر، بهتر است از extends استفاده شود. 
  • تگ include می‌­بایست دقیقاً در جایی قرار داده شود که قرار است محتوا نمایش داده شود

تگ URL


تگ {% url %} برای تولید یا برگرداندن آدرس URL استفاده می‌شود. مزیت اصلی این تگ این است که به جای نوشتن مستقیم آدرس‌ها (که ممکن است بعداً تغییر کنند)، از نام مسیر (name) که در هنگام تعریف الگوهای URL در urls.py مشخص شده، استفاده می‌کنیم. به این ترتیب اگر مسیر تغییر کند، فقط کافیست در urls.py آن را اصلاح کنیم و نیازی به تغییر در همه‌ی تمپلیت‌ها نخواهیم داشت.

{% url 'urlname' %}


همچنین در صورتی‌که URL، در urls.py نیاز به پارامتر داشته باشد، می‌توان پارامترها را بعد از نام URL مطرح کرد که به دو صورت فقط مقادیر و یا کلید-مقدار (key=value) نیز قابل انتقال خواهد بود

⮜ فقط مقادیر (Position-Based)

پارامترها را به همان ترتیبی که در urls.py تعریف شده‌اند، پشت سر هم قرار می‌گیرند.

{% url 'urlname' value1 value2 %}

⮜ کلید–مقدار (Keyword Arguments)

پارامترها با نامشان ارسال می‌گردند. این روش خواناتر است و ترتیب اهمیت ندارد.

{% url 'urlname' param=value1 argument=value2 %}

تگ For


تگ {% for %} برای اجرای یک حلقه روی مجموعه‌ای از داده‌ها (مثل لیست، دیکشنری، QuerySet و ...) استفاده می‌شود. در هر تکرار حلقه، ویژگی‌های آیتم جاری در یک متغیر محلی در دسترس قرار می‌گیرد.

{% for item in list %}
    {{ item }}
{% endfor %}

در جنگو می‌توان با استفاده از کلمه‌ی کلیدی reversed حلقه‌ی for را به‌صورت معکوس اجرا کرد.

{% for item in list reversed %}
    {{ item }}
{% endfor %}

با استفاده از {% empty %} می‌توان مشخص کرد اگر لیست خالی بود چه چیزی نمایش داده شود

<ul>
{% for name in names %}
    <li>{{ name }}</li>
{% empty %}
    <li>No Body Found</li>
{% endfor %}
</ul>

 

━◦○◦ نکته‌های مهم ◦○◦━

داخل حلقه‌ی for، جنگو یک متغیر ویژه به نام forloop در اختیار می‌گذارد که اطلاعات مفیدی دارد:

forloop.counter 🡠 شماره آیتم (شروع از 1)

forloop.counter0 🡠 شماره آیتم (شروع از 0)

forloop.first 🡠 درست (True) اگر اولین آیتم باشد

forloop.last 🡠 درست (True) اگر آخرین آیتم باشد

forloop.revcounter 🡠 شمارش معکوس (شروع از تعداد آیتم‌ها)

{% for name in names %}
    {% if forloop.first %}
        <strong>First Person: {{ name }}</strong><br>
    {% elif forloop.last %}
        <em>Last Person: {{ name }}</em><br>
    {% else %}
        {{ forloop.counter }} - {{ name }}<br>
    {% endif %}
{% endfor %}

تگ If


تگ {% if %} برای بررسی شرایط منطقی روی یک متغیر یا عبارت استفاده می‌شود. اگر نتیجه‌ی شرط True باشد (یعنی وجود داشته باشد، خالی نباشد و یا مقدار گزاره False نباشد) محتوای داخل بلوک نمایش داده می‌شود، در غیر این صورت، نادیده گرفته خواهد شد.:

{% if condition %}
    <p> statement! </p>
{% elif not condition %}
    <p> statement! </p>
{% elif condition and ( condition or condition ) %}
    <p> statement! </p>
{% else %}
    <p> statement! </p>
{% endif %}

condition هر متغیر یا عبارتی است که قابلیت ارزیابی به True / False داشته باشد.

 

━◦○◦ نکته‌های مهم ◦○◦━

شرایطی که False محسوب می‌شوند

 ⮜ مقدار False

⮜ مقدار None

⮜ رشته‌ی خالی ''

⮜ لیست یا دیکشنری خالی [] یا {}

⮜ عدد صفر 0

در غیر این صورت شرط، True در نظر گرفته می‌شود.