اگر تا اینجای کار درگیر منطق‌های پایتونی و جداول دیتابیس بودید، حالا وقت آن است که تمام آن داده‌های خام را به یک ظاهر زیبا و کاربرپسند تبدیل کنید. تمپلیت در جنگو (Django Templates) همان لایه نهایی است که کاربر مستقیماً با آن تعامل دارد. در این درس، یاد می‌گیریم چطور داده‌های آگهی‌های استخدام را از ویوها بگیریم و با استفاده از HTML و موتور قدرتمند جنگو، آن‌ها را به شکلی حرفه‌ای نمایش دهیم.

موتور تمپلیت جنگو؛ فراتر از یک HTML ساده

اشتباه نکنید! فایل‌های تمپلیت فقط کدهای استاتیک HTML نیستند. جنگو از یک زبان نشانه‌گذاری هوشمند به نام DTL (Django Template Language) استفاده می‌کند.

این زبان به شما اجازه می‌دهد منطق‌های برنامه‌نویسی را مستقیماً وارد ظاهر سایت کنید. تمپلیت جنگو به شما اجازه می‌دهد بدون نوشتن کدهای پیچیده جاوا اسکریپت، لیست آگهی‌ها را با حلقه‌ها نمایش دهید یا برای کاربران لاگین شده پیام‌های اختصاصی بفرستید.

در یک سایت کاریابی، شما با داده‌های متغیر سر و کار دارید. یک روز ۱۰ آگهی دارید و روز دیگر ۱۰۰۰ آگهی. سیستم تمپلیتینگ در جنگو به شما کمک می‌کند یک قالب ثابت طراحی کنید و اجازه دهید جنگو خودش محتوا را درون آن تزریق کند.

مفاهیم کلیدی که در این واحد مسلط می‌شوید:

  • ارث‌بری تمپلیت (Template Inheritance): چطور یک ساختار کلی برای سایت بسازید و فقط بخش‌های میانی را تغییر دهید تا از تکرار کد جلوگیری کنید.
  • تگ‌ها و فیلترها: چطور تاریخ‌ها را شمسی کنید یا متن‌های طولانی را به صورت خودکار خلاصه کنید.
  • مدیریت فایل‌های استاتیک: نحوه اضافه کردن CSS و تصاویر برای جذاب‌تر کردن ظاهر پروژه.
  • فولدر Templates: محلی که تمام فایل‌های ظاهری پروژه در آن قرار می‌گیرند.
  • نحو (Syntax) تگ‌ها: کار با ابزارهایی مثل {% for %} و {{ variable }}.
  • یکپارچگی با ویوها: چطور داده‌هایی که در واحد قبلی با ListView و DetailView ساختیم را در اینجا فراخوانی کنیم.

آماده‌اید تا آگهی‌های استخدام job_tracker را از کدهای خشک پایتونی به یک سایت واقعی و شکیل تبدیل کنیم؟ بیایید با هم اولین قدم، یعنی تنظیمات پوشه تمپلیت را در فایل settings.py بررسی کنیم.

تنظیمات پوشه Templates و ساختار فایل‌های پروژه

قبل از اینکه اولین خط کد HTML را بنویسید، باید به جنگو بگویید که فایل‌های ظاهری سایت را کجا مخفی کرده‌اید. جنگو به صورت پیش‌فرض نمی‌داند تمپلیت‌های پروژه شما در کدام پوشه هستند. تنظیم درستِ ساختار فایل‌ها در جنگو نه‌تنها از بروز خطای معروف TemplateDoesNotExist جلوگیری می‌کند، بلکه باعث می‌شود مدیریت پروژه در آینده به یک کابوس تبدیل نشود.

قدم اول: معرفی نقشه راه در settings.py

برای شروع، باید به فایل settings.py در پوشه اصلی پروژه (نه پوشه های مربوط به اپ ها) بروید و متغیر TEMPLATES را پیدا کنید. در بخش DIRS مشخص می‌کنیم که جنگو باید در کدام مسیر دنبال فایل‌های ما بگردد:

'DIRS': [BASE_DIR / 'templates'],

با این تغییر ساده، شما به جنگو دستور می‌دهید که یک پوشه به نام templates در ریشه اصلی پروژه ساخته اید و تمام فایل‌های HTML را آنجا قرار داده اید. 

ساختار درختی و اصولی فایل‌ها

حرفه‌ای‌ها هیچ‌وقت تمام فایل‌های HTML را به صورت نامنظم در پوشه تمپلیت نمی‌ریزند. برای پروژه‌ای مثل job_tracker که بخش‌های مختلفی ممکن است داشته باشد، باید از ساختار زیرمجموعه‌ای استفاده کنید. پیشنهاد ما برای نظم‌دهی به پروژه شما این است:

templates/base.html: فایل مادر که هدر و فوتر در آن قرار دارد.

templates/includes/: برای قطعات کوچک کد مثل دکمه‌ها یا منوهای تکراری.

templates/jobs/ - در اپ jobs برای فایل های اختصاصی این اپ: همانطور که در درس های قبل گفته شد و انجام داده شد، پوشه ای با نام templates نیز در اپ jobs ساختیم و در این پوشه، پوشه دیگری با نام jobs که هم نام با نام اپ می باشد، نیز ایجاد کردیم. در این پوشه تمام فایل های html اختصاصی مربوط به این اپ که قرار هست از فایل base.html پیروی کند، قرار داده شده است(مثل لیست و جزئیات).

این مدل از فولدر بندی پروژه جنگو باعث می‌شود وقتی تیم شما بزرگ‌تر شد، هر برنامه‌نویس دقیقاً بداند برای تغییر ظاهرِ یک بخش خاص باید سراغ کدام فایل برود.

نکات مهم این بخش برای شما:

رفع خطاهای رایج: یاد گرفتید چطور ریشه اصلی خطا در عدم شناسایی تمپلیت‌ها را بخشکانید.

نظم حرفه‌ای: پروژه‌تان از حالت "تمرینی" به حالت "آماده برای بازار کار" تغییر کرد.

مقیاس‌پذیری: حالا آماده‌اید تا بدون ترس از شلوغی، ده‌ها صفحه جدید به سایت اضافه کنید.

زبان تمپلیت جنگو (DTL) و سینتکس دابل براکت

فایل‌های HTML معمولی ایستا هستند؛ یعنی هر چه در آن‌ها بنویسید، همان را به کاربر نشان می‌دهند. اما در سایت یا پروژه job_tracker، ما نیاز داریم اطلاعات هر آگهی را به صورت پویا (داینامیک) نمایش دهیم.

اینجاست که زبان تمپلیت جنگو (DTL) وارد بازی می‌شود. این زبان مثل یک پل ارتباطی عمل می‌کند که داده‌ها را از دنیای پایتون می‌گیرد و در دل کدهای فرانت‌اند شما یا همان فایل های html قرار می‌دهد.

سینتکس دابل براکت {{ }}؛ جادوی نمایش متغیرها

ساده‌ترین و پرکاربردترین بخش DTL، استفاده از دو آکولاد باز و بسته است. وقتی شما در ویو (View) متغیری مثل job را به تمپلیت می‌فرستید، برای نمایش عنوان آن در صفحه وب، کافی است بنویسید:

<h1>{{ job.title }}</h1>

جنگو به محض دیدن این علامت، می‌فهمد که نباید خودِ کلمه "job.title" را چاپ کند، بلکه باید به دیتابیس برود و مقدار واقعی آن (مثلاً "برنامه‌نویس پایتون") را جایگزین کند. 

دسترسی به ویژگی‌ها با نقطه (Dot Notation)

یکی از جذابیت‌های زبان تمپلیتینگ در جنگو این است که شما می‌توانید با استفاده از یک نقطه، به تمام ویژگی‌های یک شیء دسترسی پیدا کنید. اگر می‌خواهید نام شرکتی که آگهی را ثبت کرده نمایش دهید، کد شما به این صورت خواهد بود:

<span>شرکت: {{ job.company.name }}</span>

جنگو آنقدر هوشمند است که خودش می‌فهمد باید از مدل Job به سراغ مدل Company برود و نام آن را استخراج کند. این یعنی شما بدون نوشتن کدهای پیچیده در سمت فرانت‌اند، به تمام قدرت دیتابیس خود دسترسی دارید.

ارث‌بری تمپلیت (Template Inheritance): معجزه فایل base.html

نوشتن کدهای تکراری برای هدر، فوتر و منوها در تک‌تک صفحات، نه تنها وقت‌گیر است بلکه احتمال خطا را هم بالا می‌برد. تصور کنید بخواهید یک گزینه به منوی سایت اضافه کنید؛ آیا منطقی است که ۵۰ فایل HTML را ویرایش کنید؟ قطعاً نه.

ارث‌بری تمپلیت در جنگو (Template Inheritance) دقیقاً برای حل این چالش به وجود آمده است تا با یک بار کدنویسی، ساختار کل سایت را مدیریت کنید.

فایل base.html؛ ستون فقرات سایت شما

در این روش، ما یک فایل اصلی به نام base.html می‌سازیم. این فایل حاوی تمام بخش‌های ثابت سایت مثل تگ‌های Meta، لینک‌های CSS، هدر و فوتر است. اما برای بخش‌هایی که در هر صفحه تغییر می‌کنند (مثل لیست آگهی‌ها یا جزئیات شغل)، از حفره‌هایی به نام Block استفاده می‌کنیم.

بهترین و استانداردترین مکان برای این فایل، پوشه templates در ریشه اصلی پروژه (همان‌جایی که فایل manage.py قرار دارد) است. اگر طبق آموزش قبلی، تنظیمات DIRS را در settings.py انجام داده باشید، جنگو مستقیماً سراغ این پوشه می‌رود.

مسیر پیشنهادی: JobTrack/templates/base.html

کدهای داخل فایل base.html

این فایل شامل ساختار اصلی HTML است. به بخش‌های {% block %} دقت کنید؛ این‌ها همان "جایگاه‌های خالی" هستند که صفحات دیگر آن‌ها را پر می‌کنند.

<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}پنل کاریابی JobTrack{% endblock %}</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header>
        <nav>
            <a href="/">صفحه اصلی</a>
            <a href="/jobs">آگهی‌ها</a>
        </nav>
    </header>

    <main>
        {% block content %}
        {% endblock %}
    </main>

    <footer>
        <p>© 2026 تمام حقوق برای JobTrack محفوظ است.</p>
    </footer>
</body>
</html>

اجزای اصلی ارث‌بری: بلاک‌ها و تمدیدها

برای اینکه از این قالب در صفحات دیگر (مثل لیست آگهی‌ها) استفاده کنید، باید با دو مفهوم کلیدی آشنا شوید:

۱. تگ Block: حفره‌های هوشمند

هر جا که بنویسید {% block name %}، در واقع دارید یک نقطه قابل تغییر در سایت ایجاد می‌کنید. در فایل base.html بالا، ما دو بلاک ساختیم:

block title: برای اینکه عنوان هر صفحه (مثلاً "جزئیات آگهی") با بقیه فرق کند.

block content: بدنه اصلی صفحه که محتوای هر بخش در آن ریخته می‌شود.

۲. تگ Extends: اتصال به ریشه

وقتی می‌خواهید یک صفحه جدید بسازید، اولین خط کد شما باید {% extends 'base.html' %} باشد. این یعنی: «ای جنگو، برو تمام کدهای base.html را بیاور، من فقط می‌خواهم داخل بلاک‌ها را پر کنم.»

یک مثال عملی: صفحه لیست آگهی‌ها

حالا باید فایل جدیدی با نام job_list.html در اپ jobs که قبلا ساختم ایجاد کنیم.

برای اینکه پروژه JobTrack طبق استانداردهای حرفه‌ای جنگو پیش برود، محل قرارگیری فایل‌های فرزند مثل job_list.html بسیار مهم است. هرچند می‌توانید همه فایل‌ها را در پوشه اصلی تمپلیت بریزید، اما روش اصولی (Best Practice) این است که برای هر اپلیکیشن، یک زیرپوشه هم‌نام با آن اپلیکیشن بسازید.

بنابراین، اگر نام اپلیکیشن شما jobs است، فایل لیست آگهی‌ها را باید در مسیر templates/jobs/job_list.html ایجاد کنید. این ساختار درختی باعث می‌شود که اگر در آینده اپلیکیشن‌های دیگری مثل «وبلاگ» یا «پنل کاربری» اضافه کردید، تمپلیت‌های آن‌ها با هم تداخل پیدا نکنند و جنگو دقیقاً بداند کدام فایل متعلق به کدام بخش است.

در این ساختار، فایل مادر یعنی base.html در ریشه پوشه تمپلیت می‌ماند تا برای همه در دسترس باشد، اما فایل‌های اختصاصی هر بخش در "پوشه امن" خودشان قرار می‌گیرند. این نظم و انضباط در ساختار پوشه‌بندی جنگو، ریسک خطاهای نام‌گذاری را به صفر می‌رساند و فرآیند دیباگ کردن را در پروژه‌های بزرگ سال ۲۰۲۶ به‌شدت سرعت می‌بخشد.


حالا کد زیر را در فایل job_list.html بنویسید. میبینید که فایل job_list.html چقدر خلوت و تمیز می‌شود:

{% extends 'base.html' %}

{% block title %}لیست آگهی‌های استخدام{% endblock %}

{% block content %}
    <h1>فرصت‌های شغلی جدید</h1>
    <p>در این قسمت آگهی‌های متناسب با مهارت خود را پیدا کنید.</p>
    {% endblock %}

یک نکته طلایی

شما می‌توانید چندین بلاک در فایل base.html داشته باشید. مثلاً یک بلاک برای عنوان صفحه (title) و یک بلاک برای کدهای جاوا اسکریپت اختصاصی هر صفحه. این کار دست شما را برای شخصی‌سازی هر بخش از سایت JobTrack کاملاً باز می‌گذارد.

کار با حلقه‌ها و شرط‌ها: نمایش لیست آگهی‌های استخدام

تا این‌جا یاد گرفتیم چطور اسکلت سایت را بسازیم، اما یک صفحه وب بدون محتوا شبیه به یک ساختمان خالی است. در پروژه JobTrack، هدف اصلی ما نشان دادن لیست شغل‌ها به کاربران است. اما چطور می‌توانیم لیستی از آگهی‌ها را که تعدادشان مدام تغییر می‌کند، در فایل HTML نمایش دهیم؟ پاسخ در دو ابزار قدرتمند حلقه‌ها (Loops) و شرط‌ها (Conditions) نهفته است.

حلقه for: موتور چاپ خودکار آگهی‌ها

در واحد قبلی، لیستی از مشاغل را تحت عنوان all_jobs از ویو به تمپلیت فرستادیم. حالا با استفاده از تگ {% for %}، به جنگو دستور می‌دهیم که روی تک‌تک این آگهی‌ها حرکت کند و اطلاعات آن‌ها را برای ما چاپ کند.

کد زیر را در فایل job_list.html و داخل بلاک content بنویسید:

{% for job in all_jobs %}
    <div class="job-card">
        <h3>{{ job.title }}</h3>
        <p>شرکت: {{ job.company }}</p>
        <p>حقوق: {{ job.salary }} تومان</p>
    </div>
{% empty %}
    <p>در حال حاضر هیچ آگهی استخدامی ثبت نشده است.</p>
{% endfor %}

تگ {% empty %} یک قابلیت نجات‌بخش است؛ اگر دیتابیس خالی باشد، به جای اینکه صفحه سفید و بی‌روح بماند، یک پیام محترمانه به کاربر نشان می‌دهد. کلمه کلیدی نمایش لیست در تمپلیت جنگو دقیقاً با همین حلقه معنا پیدا می‌کند.

شرط if: هوشمندسازی نمایش محتوا

گاهی نمی‌خواهیم تمام اطلاعات برای همه یکسان باشد. مثلاً شاید بخواهید آگهی‌هایی که برچسب "فوری" دارند را با رنگ قرمز نشان دهید، یا اگر آگهی منقضی شده، دکمه "ارسال رزومه" را مخفی کنید. اینجاست که تگ {% if %} وارد می‌شود.

به این مثال نگاه کنید:

{% if job.is_urgent %}
    <span class="badge-red">استخدام فوری!</span>
{% endif %}

{% if job.salary > 20000000 %}
    <p>وضعیت حقوق: عالی</p>
{% else %}
    <p>وضعیت حقوق: طبق وزارت کار</p>
{% endif %}

ارزشی که این بخش به پروژه اضافه کرده است:

داینامیک بودن: سایت شما با اضافه شدن هر آگهی جدید در پنل ادمین، به صورت خودکار آپدیت می‌شود.

تجربه کاربری حرفه‌ای: کاربر به جای دیدن خطاهای عجیب، پیام‌های منطقی (مثل "آگهی یافت نشد") دریافت می‌کند.

نظم در فرانت‌اِند: کدهای HTML شما کوتاه، خوانا و قابل فهم باقی می‌مانند.

فیلترها و تگ‌های کاربردی: شخصی‌سازی نمایش داده‌ها

گاهی اوقات داده‌هایی که از دیتابیس استخراج می‌کنیم، دقیقاً همان شکلی نیستند که کاربر دوست دارد ببیند. مثلاً نمایش یک تاریخ میلادیِ خشک و خالی یا متنی که بیش از حد طولانی است، ظاهر سایت JobTrack را به‌هم می‌ریزد. فیلترهای تمپلیت در جنگو (Django Template Filters) مثل یک رتوش‌کار حرفه‌ای عمل می‌کنند؛ آن‌ها داده خام را می‌گیرند و آن را برای نمایش در ویترین سایت، زیبا و استاندارد می‌کنند.

جادوی علامت پین ( | ): تغییر در لحظه

در زبان تمپلیت جنگو، برای اعمال فیلتر از علامت | (Pipe) استفاده می‌کنیم. این علامت به جنگو می‌گوید: «اول داده را بگیر، بعد آن را از این فیلتر عبور بده و در نهایت نتیجه را چاپ کن.»

بیایید چند مثال واقعی که در پروژه به آن‌ها نیاز دارید را بررسی کنیم:

خلاصه کردن متن (Truncate):

اگر توضیحات یک آگهی خیلی طولانی است و می‌خواهید فقط ۲۰ کلمه اول آن را در صفحه اصلی نشان دهید:

{{ job.description|truncatewords:20 }}

تغییر حروف به بزرگ یا کوچک:

برای نمایش استایل‌دار نام شرکت‌های بین‌المللی:

{{ job.company_name|upper }}

نمایش مقدار پیش‌فرض:

اگر فیلدی در دیتابیس خالی بود (مثل حقوق)، به جای خالی گذاشتن صفحه، یک متن جایگزین نشان دهید:

{{ job.salary|default:"توافقی" }}

تگ‌های کاربردی؛ فراتر از نمایش ساده

علاوه بر فیلترها، ما تگ‌هایی داریم که کارهای منطقی انجام می‌دهند. یکی از پرکاربردترین آن‌ها در پروژه‌های فارسی، مدیریت زمان و تاریخ است. با استفاده از تگ‌های داخلی و فیلتر date می‌توانید نحوه نمایش زمان انتشار آگهی را کاملاً شخصی‌سازی کنید تا کاربر بفهمد این فرصت شغلی چقدر تازه است.

چرا شخصی‌سازی داده‌هاحیاتی است؟

  • خوانایی محتوا (Readability): وقتی توضیحات طولانی را به درستی در لیست‌ها خلاصه می‌کنید، کاربر سریع‌تر محتوای مورد نظرش را پیدا می‌کند. این کار نرخ پرش (Bounce Rate) را به شدت کاهش می‌دهد.
  • جلوگیری از محتوای تکراری: با فیلترهایی مثل lower یا capfirst می‌توانید ظاهر داده‌های ورودی کاربران مختلف را یکسان‌سازی کنید تا سایت شما از نظر بصری و ساختاری، حرفه‌ای و یکپارچه به نظر برسد.
  • تجربه کاربری موبایل: استفاده از فیلترهایی که طول متون را کنترل می‌کنند، باعث می‌شود چیدمان سایت شما در گوشی‌های هوشمند به‌هم نریزد؛ فاکتوری که مستقیماً روی رتبه سئو تاثیر دارد.

 

لینک‌سازی هوشمند با تگ url: اتصال صفحات به یکدیگر

در دنیای طراحی وب، هیچ‌چیز بدتر از یک لینک شکسته یا آدرسی نیست که با تغییر ساختار سایت از کار می‌افتد. اگر در پروژه JobTrack بخواهید به سبک قدیمی آدرس‌ها را دستی بنویسید (مثلاً /jobs/5/)، با اولین تغییر در فایل urls.py کل سایت شما از کار می‌افتد. لینک‌سازی هوشمند در جنگو با استفاده از تگ {% url %} این مشکل را برای همیشه حل می‌کند. این تگ به جای تکیه بر آدرس‌های خشک و ثابت، به نامِ مسیرها نگاه می‌کند.

تگ url چطور کار می‌کند؟

وقتی می‌خواهید کاربر را از لیست آگهی‌ها به صفحه جزئیات یک شغل خاص بفرستید، به جای نوشتن آدرس مستقیم، از نامی که در تنظیمات URL برای آن صفحه انتخاب کرده‌اید استفاده می‌کنید. جنگو خودش در لحظه می‌گردد و آدرس صحیح را جایگزین می‌کند.

به این مثال کاربردی نگاه کنید:

<a href="{% url 'job_detail' job.id %}">مشاهده جزئیات آگهی</a>

در این کد، job_detail نام مسیر ماست و job.id همان عددی است که مشخص می‌کند کاربر باید کدام آگهی را ببیند. با این روش، اگر فردا تصمیم بگیرید کلمه jobs را در آدرس سایت به careers تغییر دهید، نیازی نیست حتی یک خط از کدهای تمپلیت را دستکاری کنید. (در درس بعدی به صورت مفصل تر در مورد url ها صحبت خواهیم کرد)

چرا لینک‌سازی داینامیک مهم است؟

موتورهای جستجو به شدت روی "پایداری آدرس‌ها" حساس هستند. اشتباه در لینک‌سازی داخلی نه تنها کاربر را سردرگم می‌کند، بلکه نمره منفی بزرگی در کارنامه سئو شما ثبت می‌کند.

جلوگیری از خطای ۴۰۴: چون آدرس‌ها توسط خودِ موتور جنگو ساخته می‌شوند، احتمال تایپ اشتباه آدرس به صفر می‌رسد.

ساختار سلسله‌مراتبی تمیز: با استفاده از تگ url در جنگو، شما به راحتی می‌توانید ساختار لینک‌های "Breadcrumb" (راهنمای مسیر) را بسازید که گوگل برای درک موضوعی صفحات عاشق آن‌هاست.

انعطاف در تغییرات: شما می‌توانید بدون ترس از جریمه‌های گوگل بابت لینک‌های شکسته، معماری آدرس‌های سایت (URL Structure) خود را هر زمان که لازم بود بازنویسی و بهینه کنید.

تاثیر این بخش بر روی پروژه:

کدنویسی ضدضربه: سایت شما در برابر تغییرات ساختاری مقاوم می‌شود.

مدیریت آسان: دیگر لازم نیست نگران باشید که کدام صفحه به کجا لینک داده شده است؛ نام‌ها همه کار را انجام می‌دهند.

سرعت توسعه: به جای گشتن دنبال آدرس‌های دقیق، فقط با صدا زدن نام صفحه، لینک را می‌سازید.

نکته :
اگر از namespace در فایل‌های URL خود استفاده می‌کنید، یادتان باشد که نام را به صورت {% url 'jobs:job_detail' job.id %} بنویسید. این کار باعث می‌شود حتی اگر چندین اپلیکیشن با نام‌های مشابه داشته باشید، جنگو هرگز گیج نشود.

حالا که صفحات سایت به هم متصل شدند، ظاهر سایت هنوز کمی "بی‌روح" است. موافقید در بخش آخر یاد بگیریم چطور با استفاده از "فایل‌های استاتیک"، رنگ و لعاب و تصاویر را به JobTrack اضافه کنیم؟

مدیریت فایل‌های استاتیک (Static Files): اضافه کردن CSS و تصاویر

یک سایت استخدامی هرچقدر هم که دیتابیس قوی داشته باشد، بدون ظاهر آراسته، اعتماد کاربران را جلب نمی‌کند. فایل‌های استاتیک در جنگو (Static Files) شامل کدهای CSS برای رنگ و لعاب، کدهای جاوا اسکریپت برای تعامل و تصاویری مثل لوگوی سایت هستند. جنگو برای مدیریت این فایل‌ها استراتژی خاصی دارد تا سرعت لود صفحات شما در بالاترین سطح باقی بماند.

کجا فایل‌های استاتیک را ذخیره کنیم؟

در جنگو شما دو راه برای سازماندهی فایل‌ها دارید:

پوشه Static گلوبال: بهترین مکان برای فایل‌هایی که در کل سایت مشترک هستند (مثل فونت‌ها یا استایل‌های اصلی). این پوشه را در ریشه پروژه کنار manage.py بسازید.

پوشه Static اختصاصی: اگر یک اپلیکیشن خاص (مثل jobs) استایل‌های منحصربه‌فردی دارد، می‌توانید داخل پوشه همان اپ، یک پوشه به نام static بسازید سپس در این پوشه باید یک پوشه دیگر همنام اپ بسازید و در این پوشه فایل های استاتیک خود را قرار دهید(همانند ساختار پوشه تمپلیت ها در اپ که در بخش های بالاتر گفتیم). جنگو با هوشمندی تمام، این فایل‌ها را پیدا می‌کند. به الگوی زیر دقت کنید:

static/jobs/style.css

معرفی فایل‌های استاتیک به تمپلیت
برای اینکه بتوانید از این فایل‌ها در HTML استفاده کنید، ابتدا باید در اولین خط فایل (بالای {% extends %}) تگ بارگذاری را بنویسید:

{% load static %}

سپس برای فراخوانی یک فایل CSS یا تصویر، از تگ مخصوص آن استفاده کنید:

<link rel="stylesheet" href="{% static 'css/style.css' %}">
<img src="{% static 'images/logo.png' %}" alt="لوگوی JobTrack">

جادوی دستور Collectstatic

وقتی پروژه JobTrack آماده انتشار می‌شود، شما نباید فایل‌های استاتیک را به صورت پراکنده رها کنید. جنگو دستوری به نام python manage.py collectstatic دارد. با زدن این دستور، جنگو تمام فایل‌های استاتیک را از تمام پوشه‌های گلوبال و اپلیکیشن‌ها جمع‌آوری کرده و در یک پوشه واحد (معمولاً به نام staticfiles) می‌ریزد. این کار باعث می‌شود سرور شما (مثل Nginx) بتواند با سرعت بسیار بالاتری این فایل‌ها را به مرورگر کاربر تحویل دهد.

مدیریت صحیح استاتیک‌ها به دلایل زیر مهم است:

در استانداردهای جدید وب، پارامتری به نام "LCP" (زمان بارگذاری بزرگترین محتوا) به شدت اهمیت دارد:

  • کشینگ هوشمند (Caching): با متمرکز کردن فایل‌ها در پوشه نهایی، مرورگرها می‌توانند استایل‌ها را کش کنند تا در مراجعات بعدی، سایت شما زیر ۱ ثانیه لود شود.
  • جلوگیری از خطاهای رندرینگ: استفاده از تگ {% static %} تضمین می‌کند که آدرس تصاویر شما همیشه درست بماند، حتی اگر دامنه سایت را عوض کنید. گوگل به سایت‌هایی که تصاویر شکسته ندارند، امتیاز بالاتری می‌دهد.
  • بهینه‌سازی تصاویر: با مدیریت متمرکز، می‌توانید به راحتی ابزارهای فشرده‌سازی را روی پوشه نهایی اعمال کنید تا حجم صفحه کاهش یابد.

تنظیمات کلیدی در settings.py

برای اینکه این سیستم کار کند، باید سه متغیر مهم را تنظیم کنید:

STATIC_URL: آدرسی که در مرورگر برای دسترسی به فایل‌ها استفاده می‌شود (مثلاً /static/).

STATICFILES_DIRS: لیست مسیرهایی که جنگو باید در زمان توسعه دنبال فایل‌های استاتیک بگردد (پوشه گلوبال شما).

STATIC_ROOT: آدرس پوشه نهایی که دستور collectstatic تمام فایل‌ها را آنجا جمع می‌کند (مخصوص زمان انتشار).

تبریک می‌گویم! شما حالا یاد گرفتید چطور به کالبد بی‌روح کدهای پایتون، رنگ و زندگی ببخشید. با پایان این درس، پروژه JobTrack از یک اسکریپت ساده به یک وب‌سایت واقعی تبدیل شده است.