به موتور متفکر وب‌سایت خود خوش آمدید! اگر دیتابیس را قلب و قالب‌ها را ویترین سایت بدانیم، ویو در جنگو (Django Views) دقیقاً همان مغز هوشمندی است که تصمیم می‌گیرد چه اطلاعاتی، در چه زمانی و به چه شکلی به کاربر نمایش داده شود.

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

ویو در جنگو؛ پل ارتباطی کاربر و دیتابیس

در دنیای توسعه وب با جنگو، هر بار که شخصی آدرسی را در مرورگر وارد می‌کند، یک "درخواست" (Request) به سمت سرور ارسال می‌شود.

وظیفه اصلی شما به عنوان برنامه‌نویس این است که در فایل views.py مشخص کنید برای این درخواست چه پاسخی (Response) ارسال شود. 

چرا در پروژه JobTrack به ویوها نیاز مبرم داریم؟

تصور کنید صدها آگهی استخدام در پنل مدیریت ثبت کرده‌اید. بدون نوشتن یک ویوی درست، این آگهی‌ها در دیتابیس حبس می‌مانند و هیچ کاربری نمی‌تواند آن‌ها را ببیند. در این درس، ما یاد می‌گیریم:

  • استخراج هوشمند داده‌ها: چطور فقط آگهی‌های "فعال" را از مدل Job فراخوانی کنیم.
  • ارسال داده به قالب: چطور لیست شغل‌ها را به دست فایل‌های HTML برسانیم تا کاربر آن‌ها را در محیطی زیبا مشاهده کند.
  • مدیریت پاسخ‌ها: آشنایی با انواع خروجی‌ها، از یک متن ساده گرفته تا صفحات پیچیده وب.

رویکردهای مدرن در طراحی ویوها (FBVs vs CBVs)

در سال ۲۰۲۶، انتخاب بین ویوهای تابعی (Function-Based Views) و ویوهای کلاس‌محور (Class-Based Views) یکی از بحث‌های داغ میان توسعه‌دهندگان است. ویوهای تابعی به دلیل سادگی و خوانایی بالا برای شروع عالی هستند، در حالی که کلاس‌ها قدرت عجیبی در جلوگیری از تکرار کد (DRY) دارند. ما در این واحد، هر دو روش را بررسی می‌کنیم تا شما بتوانید در پروژه‌های واقعی، بهترین ابزار را برای حل مسئله انتخاب کنید.

ویوهای تابعی (function based views): ساده‌ترین راه برای شروع گفتگو با کاربر

در دنیای توسعه وب با پایتون، هیچ‌چیز به اندازه ویوهای تابعی (Function-Based Views) صریح و شفاف نیست. این ویوها که به اختصار FBV نامیده می‌شوند، ساده‌ترین و مستقیم‌ترین روش برای نوشتن منطق سایت هستند.

در واقع، یک FBV چیزی نیست جز یک تابع معمولی پایتون که یک درخواست (Request) از کاربر می‌گیرد و پس از انجام پردازش‌های لازم، یک پاسخ (Response) تحویل می‌دهد.

چرا یادگیری FBV برای هر جنگوکار ضروری است؟

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

بیایید اولین ویوی خود را در فایل views.py بنویسیم:

from django.http import HttpResponse

def job_list_view(request):
    return HttpResponse("لیست آگهی‌های شغلی به زودی در اینجا نمایش داده می‌شود.")

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

کالبدشکافی یک ویوی تابعی

یک ویوی تابعی استاندارد از سه بخش اصلی تشکیل شده است:

  • ورودی (Request): شیئی که حاوی تمام اطلاعات کاربر (مثل آدرس IP، نوع مرورگر یا داده‌های ارسالی) است.
  • بدنه (Logic): جایی که شما با دیتابیس حرف می‌زنید یا محاسبات را انجام می‌دهید.
  • خروجی (Response): نتیجه نهایی که می‌تواند یک متن ساده، یک فایل HTML یا حتی یک خطای ۴۰۴ باشد.

ارزش افزوده: چه زمانی از FBV استفاده کنیم؟

طبق ترندهای برنامه‌نویسی پایتون در سال ۲۰۲۶، خوانایی کد (Readability) بر پیچیدگی‌های غیرضروری اولویت دارد. ویوهای تابعی برای سناریوهایی که منطق اختصاصی و خاصی دارند، بهترین انتخاب هستند. برخلاف ویوهای کلاس‌محور که گاهی رفتارهای پنهانی دارند، در FBV همه‌چیز "عیان" است.

استفاده از این روش در ابتدای یادگیری، درک شما را از معماری MTV در جنگو به شدت عمیق می‌کند. شما یاد می‌گیرید که وب در حقیقت چیزی جز یک چرخه بی‌پایان از "درخواست و پاسخ" نیست.

نکات کلیدی برای موفقیت در این بخش:

نام‌گذاری معنادار: نام توابع ویو را طوری انتخاب کنید که با هدف صفحه (مثلاً نمایش لیست یا جزئیات) همخوانی داشته باشد.

ورودی اجباری: فراموش نکنید که اولین ورودی هر ویوی تابعی حتماً باید پارامتر request باشد.

بازگشت پاسخ: هر تابعی که می‌نویسید، "باید" یک خروجی از نوع Response برگرداند، در غیر این صورت جنگو با عصبانیت به شما ارور خواهد داد!

کار با HttpRequest و HttpResponse: پشت‌صحنه درخواست‌های وب

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

HttpRequest: بسته‌ای پر از اطلاعات کاربر

هر زمان که یک ویو را در جنگو می‌سازید، اولین ورودی آن request است. این پارامتر فقط یک کلمه ساده نیست؛ بلکه یک شیء عظیم از کلاس HttpRequest است که تمام جزئیات کاربر را در خود جای داده است. از طریق این شیء، شما می‌توانید بفهمید:

  • کاربر چه چیزی را جستجو کرده است؟ (از طریق request.GET)
  • آیا فرمی را پر کرده و فرستاده است؟ (از طریق request.POST)
  • آیا کاربر لاگین کرده یا یک مهمان ناشناس است؟ (request.user)
  • آدرس IP و نوع مرورگر او چیست؟

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

HttpResponse: پاسخ نهایی و ویترین کار شما

بعد از اینکه ویوی شما درخواست را تحلیل کرد، نوبت به ارسال پاسخ می‌رسد. شما نمی‌توانید یک رشته متن ساده را همین‌طوری به سمت مرورگر پرتاب کنید! جنگو باید این متن را در قالب یک شیء استاندارد به نام HttpResponse بسته‌بندی کند. این بسته حاوی کدهای وضعیت (Status Codes) است که به مرورگر می‌گوید همه‌چیز مرتب است (کد ۲۰۰) یا مشکلی وجود دارد (مثل کد ۴۰۴).

در کدهای واحد قبلی، ما از این ابزار استفاده کردیم:

from django.http import HttpResponse

def simple_view(request):
    return HttpResponse("درخواست شما با موفقیت دریافت شد!")

چرا این مفاهیم در سال ۲۰۲۶ حیاتی‌تر شده‌اند؟

با پیشرفت الگوریتم‌های گوگل، پروتکل HTTP/3 و امنیت داده‌ها اهمیت دوچندانی پیدا کرده است. جنگو با مدیریت هوشمندانه Headerها در HttpResponse، امنیت سایت شما را در برابر حملات تزریق کد تضمین می‌کند. یادگیری کار با این اشیاء به شما کمک می‌کند تا پاسخ‌هایی بهینه و کم‌حجم تولید کنید که مستقیماً روی سرعت بارگذاری (Core Web Vitals) و در نتیجه سئو سایت تاثیر می‌گذارد.

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

دیباگ حرفه‌ای: وقتی بدانید داده‌ها کجا ذخیره می‌شوند، پیدا کردن ارورهای منطقی در پروژه بسیار ساده‌تر می‌شود.

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

تسلط بر پروتکل وب: از یک "کدنویس" به یک "توسعه‌دهنده وب" تبدیل می‌شوید که از معماری زیربنایی اینترنت آگاه است.

استخراج داده از مدل در ویو: نمایش اولین آگهی‌های استخدام

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

جادوی QuerySet: حرف زدن با دیتابیس به زبان پایتون

برای اینکه لیست آگهی‌ها را به دست بیاورید، نیازی به نوشتن کدهای پیچیده SQL ندارید. جنگو ابزاری به نام ORM در اختیار شما می‌گذارد که با آن می‌توانید مثل آب خوردن به داده‌ها دستور بدهید. در فایل views.py پروژه JobTrack، ابتدا مدل را وارد کرده و سپس تمام رکوردها را بیرون می‌کشیم:

from .models import Job

def job_list_view(request):
    # کشیدن تمام آگهی‌ها از دیتابیس
    jobs = Job.objects.all() 
    return HttpResponse(f"تعداد آگهی‌های موجود: {jobs.count()}")

در این کد، دستور Job.objects.all() یک QuerySet شامل تمام شغل‌های ثبت شده ایجاد می‌کند. این یعنی شما توانسته‌اید با یک خط کد، ارتباطی امن و سریع با پایگاه داده برقرار کنید. (در بخش بعدی همین درس این ویو را با یک ویو کلاس محور جایگزین خواهیم کرد)

فیلتر کردن هوشمند؛ نمایش آگهی‌های هدفمند

در دنیای واقعی، ما نمی‌خواهیم تمام داده‌ها را به همه نشان دهیم. مثلاً نمایش آگهی‌های منقضی شده، تجربه کاربری سایت را خراب می‌کند. با استفاده از متد .filter()، می‌توانید به راحتی فقط موارد دلخواه را جدا کنید:

نمایش آگهی‌های فعال: Job.objects.filter(is_active=True)

نمایش شغل‌های یک دسته‌بندی خاص: Job.objects.filter(category__name='برنامه‌نویسی')

این فیلتر کردن‌های دقیق، بارِ پردازشی سرور را کم کرده و باعث می‌شود سرعت لود صفحات شما به شدت بالا برود. در استانداردهای سئو ۲۰۲۶، سرعت پاسخ‌دهی ویوها به دلیل اجرای کوئری‌های بهینه، یکی از فاکتورهای اصلی رتبه‌بندی است.

چرا این بخش برای پروژه JobTrack حیاتی است؟

شما با یادگیری نحوه استخراج داده از مدل، یاد می‌گیرید که چطور محتوای خام را به اطلاعات باارزش برای کاربر تبدیل کنید.

  • پویایی سایت: سایت شما دیگر یک صفحه استاتیک نیست؛ با هر آگهی جدیدی که در پنل ادمین ثبت شود، ویوی شما به صورت خودکار آن را شناسایی و آماده نمایش می‌کند.
  • نظم ساختاری: داده‌ها با همان نظمی که در مدل تعریف کردیم (مثل عنوان، شرکت و حقوق) در دسترس هستند.
  • امنیت داده: ORM جنگو به طور خودکار از حملات خطرناکی مثل SQL Injection جلوگیری می‌کند، پس با خیال راحت کوئری بزنید.

یک نکته عملی:
همیشه سعی کنید از متد .order_by('-created_at') استفاده کنید تا جدیدترین آگهی‌های استخدام در ابتدای لیست قرار بگیرند. کاربران همیشه به دنبال تازه‌ترین فرصت‌های شغلی هستند

ویوهای کلاس‌محور (class based view ): برنامه‌نویسی به سبک حرفه‌ای‌ها

اگر بخواهید در دنیای جنگو از یک کدنویس معمولی به یک توسعه‌دهنده ارشد تبدیل شوید، باید با ویوهای کلاس‌محور (Class-Based Views) رفیق شوید.

در حالی که توابع (FBV) برای کارهای ساده عالی هستند، اما وقتی پروژه JobTrack بزرگ‌تر می‌شود، نوشتن منطق‌های تکراری برای نمایش لیست‌ها یا جزئیات آگهی‌ها، باعث شلوغی و کثیف شدن کد می‌شود. CBV در جنگو این مشکل را حل می‌کند؛ چون بر پایه اصل DRY (تکرار نکردن کد) بنا شده است.

قدرت ارث‌بری: به جای اختراع چرخ، آن را سوار شوید!

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

چرا حرفه‌ای‌ها عاشق ویوهای کلاس‌محور هستند؟

استفاده از Class-Based Views مزایای ملموسی دارد که در سال ۲۰۲۶ برای هر کارفرمایی اهمیت دارد:

  • نظم خیره‌کننده: جدا کردن متدهای GET و POST به صورت متدهای مجزا در کلاس، خوانایی کد را چند برابر می‌کند.
  • قابلیت استفاده مجدد (Reusability): می‌توانید یک کلاس پایه برای تنظیمات عمومی بسازید و بقیه ویوها را از آن مشتق کنید.
  • کاهش چشمگیر خطوط کد: کارهایی که در توابع نیاز به ۱۰ خط کد داشت، در کلاس‌ها گاهی با ۳ خط انجام می‌شود.

چه زمانی از کلاس‌ها در پروژه JobTrack استفاده کنیم؟

برای کارهای استاندارد و روتین وب مثل نمایش لیست آگهی‌ها، مشاهده جزئیات یک شغل، یا فرم‌های ثبت‌نام، ویوهای کلاس‌محور بهترین انتخاب هستند. جنگو برای هر کدام از این‌ها یک کلاس "جنریک" (Generic View) دارد که مثل یک قالب آماده عمل می‌کند. اما اگر منطق شما بسیار خاص و عجیب است، همچنان می‌توانید به سراغ توابع بروید. در واقع، هنر شما در انتخاب درستِ ابزار بین این دو روش است.

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

کدنویسی تمیز (Clean Code): یاد می‌گیرید چطور با کمترین کد، بیشترین خروجی را بگیرید.

استانداردسازی: کدهای شما شبیه به کدهای توسعه‌دهندگان سطح اول دنیا در گیت‌هاب می‌شود.

آمادگی برای مقیاس‌پذیری: پروژه شما با بزرگ‌تر شدن، دچار آشفتگی و سردرگمی نمی‌شود.

استفاده از ListView: نمایش خودکار لیست آگهی‌های شغلی

در دنیای توسعه وب، نمایش یک لیست از داده‌ها (مثل آگهی‌های استخدام، محصولات یا اخبار) تکراری‌ترین کاری است که یک برنامه‌نویس انجام می‌دهد. جنگو برای اینکه شما وقتتان را تلف نکنید، ابزاری به نام ListView را طراحی کرده است. این کلاس آماده، تمام مراحلِ گرفتنِ داده از دیتابیس و آماده‌سازی آن برای نمایش را به صورت خودکار انجام می‌دهد.

ListView؛ وقتی جنگو کارهای سخت را انجام می‌دهد

در روش‌های قدیمی، باید یک تابع می‌نوشتید، مدل را صدا می‌زدید، کوئری می‌گرفتید و دستی به قالب می‌فرستادید. اما با آموزش ListView در جنگو، کافی است نام مدل و نام قالب (Template) را بگویید؛ بقیه کارها با خودِ جنگو است.

کد زیر را ببینید تا متوجه شوید چقدر همه‌چیز خلاصه شده است:

from django.views.generic import ListView
from .models import Job

class JobListView(ListView):
    model = Job
    template_name = 'jobs/job_list.html'
    context_object_name = 'all_jobs'

در جنگو، کلاس ListView مثل یک کتابدارِ فوق‌حرفه‌ای عمل می‌کند. وظیفه او این است که به قفسه‌های دیتابیس برود، تمام کتاب‌ها (یا در اینجا آگهی‌های شغلی) را بردارد، آن‌ها را گردگیری کند و روی یک میزِ مرتب به کاربر تحویل دهد.

بیایید این تکه کد را که پایه و اساس صفحه اصلی پروژه JobTrack است، خط‌به‌خط کالبدشکافی کنیم:

۱. فراخوانی قطعات پیش‌ساخته

from django.views.generic import ListView
from .models import Job

ListView: ما این کلاس را از قلبِ جنگو قرض می‌گیریم. جنگو قبلاً تمام کارهای سخت (مثل وصل شدن به دیتابیس و لیست کردن داده‌ها) را درون این کلاس انجام داده است.

مدل Job: ما باید به جنگو بگوییم که لیستِ «چه چیزی» را می‌خواهیم؟ پس مدل آگهی‌های شغلی (Job) را وارد می‌کنیم.

۲. معرفی منبع داده (Model)

class JobListView(ListView):
    model = Job

در اینجا ما یک کلاس به نام JobListView می‌سازیم که از آن کتابدارِ حرفه‌ای (ListView) ارث‌بری می‌کند. با نوشتن model = Job به جنگو دستور می‌دهیم: «برو سراغ جدولِ Job در دیتابیس و هر چه آگهی استخدامی آنجا هست را برای من بیاور.»

۳. تعیین آدرسِ ویترین (Template)

template_name = 'jobs/job_list.html'

داده‌های خام دیتابیس به درد کاربر نمی‌خورند. ما نیاز به یک فایل HTML زیبا داریم. با این خط، به جنگو می‌گوییم: «داده‌هایی که جمع کردی را به این آدرس ببر تا درون کدهای HTML قرار بگیرند.» جنگو به صورت خودکار می‌داند که باید این فایل را در پوشه templates پیدا کند.

۴. نام‌گذاری بسته برای استفاده در HTML

context_object_name = 'all_jobs'

این یکی از مهم‌ترین بخش‌ها برای راحتی کار شماست. جنگو به صورت پیش‌فرض، لیست آگهی‌ها را در بسته‌ای به نام object_list قرار می‌دهد. اما کار کردن با نامی مثل all_jobs بسیار لذت‌بخش‌تر و خواناتر است.
حالا شما در فایل HTML می‌توانید با نوشتن یک حلقه ساده پایتونی، به این صورت آگهی‌ها را نمایش دهید (در درس های بعدی این کار را انجام خواهیم داد):

{% for job in all_jobs %}

چرا این چند خط کد، بسیار مهم است؟

خداحافظی با کدهای تکراری: اگر می‌خواستید همین کار را با تابع (FBV) انجام دهید، باید ۱۰ خط کد می‌نوشتید، اما اینجا همه‌چیز در ۴ خط خلاصه شده است.

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

ارزش واقعی برای شما: با استفاده از این ساختار، شما دیگر درگیر "چگونه گرفتن داده" نمی‌شوید، بلکه تمرکزتان را روی "چگونه نمایش دادن" و تجربه کاربری (UX) سایت می‌گذارید.

چرا ListView برای پروژه JobTrack انتخاب بهتری است؟

استفاده از این کلاس جنریک، فقط برای تنبلی نیست! ListView قابلیت‌های درونی فوق‌العاده‌ای دارد که در سال ۲۰۲۶ برای هر سایتی حیاتی است:

  • صفحه‌بندی (Pagination) خودکار: اگر ۱۰۰۰ آگهی داشته باشید، با اضافه کردن فقط یک خط کد (paginate_by = 10)، جنگو آن‌ها را ۱۰ تا ۱۰ تا صفحه‌بندی می‌کند.
  • مدیریت هوشمند کوئری‌ها: جنگو در پس‌زمینه، کوئری‌های بهینه‌ای می‌زند تا سرعت سایت شما کاهش نیابد.
  • خوانایی بالا: هر برنامه‌نویس دیگری که کد شما را ببیند، در یک ثانیه می‌فهمد که این کلاس مسئول نمایش لیست آگهی‌هاست.

ارزش افزوده این بخش:

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

تمرکز بر ظاهر: به جای درگیر شدن با منطق تکراری، وقتتان را روی طراحی ویترین زیباتر برای آگهی‌ها می‌گذارید.

توسعه استاندارد: پروژه شما مطابق با استانداردهای جهانی جنگو پیش می‌رود.

حالا که لیست آگهی‌ها آماده است، فکر می‌کنید اگر تعداد آگهی‌ها به ۱۰۰۰ عدد برسد چه اتفاقی می‌افتد؟ در بخش‌های بعدی یاد می‌گیریم چطور فقط با اضافه کردن "یک کلمه" به همین کد، قابلیت صفحه‌بندی (Pagination) را فعال کنیم! موافقید ادامه دهیم؟

صفحه‌بندی (Pagination): مدیریت آگهی‌های پرشمار در یک نگاه

تصور کنید سایت JobTrack به موفقیت بزرگی رسیده و هزاران شرکت آگهی‌های خود را در آن ثبت کرده‌اند. اگر بخواهیم تمام این ۱۰۰۰ آگهی را در یک صفحه به کاربر نشان دهیم، چه اتفاقی می‌افتد؟ سرعت لود صفحه به شدت افت می‌کند، کاربر سردرگم می‌شود و گوگل هم به دلیل سنگین بودن صفحه، امتیاز منفی به سئو سایت شما می‌دهد. راه حل حرفه‌ای برای این چالش، صفحه‌بندی یا Pagination است.

فعال‌سازی صفحه‌بندی با یک خط کد!

یکی از دلایل محبوبیت ListView در جنگو، سادگی بی‌نظیر آن در مدیریت داده‌های حجیم است. برای اینکه لیست آگهی‌ها را به صفحات کوچک‌تر (مثلاً ۱۰تایی) تقسیم کنید، فقط کافی است ویژگی paginate_by را به کلاس خود اضافه کنید:

class JobListView(ListView):
    model = Job
    template_name = 'jobs/job_list.html'
    context_object_name = 'all_jobs'
    paginate_by = 10  # در هر صفحه فقط 10 آگهی نمایش داده می‌شود

با همین یک خط، جنگو در پشت‌صحنه تمام محاسبات ریاضی پیچیده را انجام می‌دهد؛ یعنی خودش می‌فهمد در صفحه دوم باید از آگهی یازدهم تا بیستم را نشان دهد. کلمه کلیدی صفحه‌بندی در جنگو یکی از مهم‌ترین تکنیک‌ها برای بهینه‌سازی عملکرد (Performance) سایت است.

 

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

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

نظم بصری: ظاهر سایت در لیست‌های طولانی به هم نمی‌ریزد.

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

نکته فنی: وقتی صفحه‌بندی را فعال می‌کنید، جنگو یک شیء به نام page_obj را به قالب شما می‌فرستد. در واحد بعدی (Templates) یاد می‌گیریم چطور با استفاده از این شیء، دکمه‌های «قبلی» و «بعدی» را در پایین سایت بسازیم.

DetailView در پروژه JobTrack: صفحه اختصاصی برای هر آگهی

بعد از اینکه کاربر در لیست کلی، آگهی مورد نظرش را پیدا کرد، نوبت به مشاهده جزئیات کامل آن می‌رسد. اینجاست که DetailView در جنگو وارد عمل می‌شود. در پروژه JobTrack، ما نمی‌خواهیم برای هر آگهی یک ویوی جداگانه بنویسیم؛ بلکه به دنبال روشی هستیم که به صورت خودکار بفهمد کاربر روی کدام شغل کلیک کرده و اطلاعات همان را از دیتابیس فراخوانی کند.

DetailView؛ هوشمندی در نمایش تکی داده‌ها

کلاس DetailView یکی از قدرتمندترین ویوهای جنریک جنگو است. این کلاس بر اساس یک شناسه منحصربه‌فرد (مثل ID یا Slug) در آدرس بار، به دیتابیس می‌رود و دقیقاً همان رکوردی را که لازم داریم بیرون می‌کشد. با این ابزار، ساختن صفحه اختصاصی آگهی به جای ده‌ها خط کد، در سه خط خلاصه می‌شود.

کد زیر را در views.py ببینید:

from django.views.generic import DetailView
from .models import Job

class JobDetailView(DetailView):
    model = Job
    template_name = 'jobs/job_detail.html'
    context_object_name = 'job'

در دنیای جنگو، کلاس DetailView مثل یک کارآگاه باهوش عمل می‌کند؛ او وظیفه دارد بین هزاران آگهی، دقیقاً همان یکی که کاربر رویش کلیک کرده را پیدا کند و تمام جزئیاتش را روی میز (همان مرورگر) بگذارد.

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

۱. فراخوانی ابزارهای مورد نیاز

from django.views.generic import DetailView
from .models import Job

خط اول: ما کلاس DetailView را از کتابخانه داخلی جنگو وارد می‌کنیم. این کلاس یک "ویوی جنریک" (Generic View) است؛ یعنی جنگو قبلاً تمام کدهای سخت و تکراری مربوط به "نمایش یک آیتم خاص" را درون این کلاس نوشته است.

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

۲. تعریف کلاس و انتخاب هدف

class JobDetailView(DetailView):
    model = Job

با نوشتن model = Job ما به جنگو می‌گوییم: «ای کارآگاه، برو سراغ جدول آگهی‌ها.»
حالا جنگو به صورت خودکار متوجه می‌شود که باید در آدرس (URL) به دنبال یک شناسه (مثل ID یا PK) بگردد تا بفهمد دقیقاً کدام آگهی را باید از دیتابیس استخراج کند. اگر آگهی پیدا نشود، خودش زحمت کشیده و خطای 404 (یافت نشد) را به کاربر نشان می‌دهد.

۳. آدرس‌دهی ویترین (Template)

template_name = 'jobs/job_detail.html'

این خط به جنگو می‌گوید: «بعد از اینکه اطلاعات آگهی را پیدا کردی، آن‌ها را به این فایل HTML بفرست تا با ظاهری زیبا به کاربر نمایش داده شود.» بدون این خط، جنگو گیج می‌شود و نمی‌داند داده‌ها را کجا باید تزریق کند.

۴. نام‌گذاری بسته اطلاعاتی (Context)

context_object_name = 'job'

این بخش بسیار مهم است! به صورت پیش‌فرض، جنگو داده‌ها را با نام object به فایل HTML می‌فرستد. اما کلمه object خیلی گنگ است. با نوشتن این خط، ما به جنگو می‌گوییم: «لطفاً در فایل HTML، این آگهی را با نام job معرفی کن.»
حالا شما در کدهای HTML خود می‌توانید خیلی راحت بنویسید: {{ job.title }} تا عنوان شغل نمایش داده شود.

چرا این روش برای پروژه JobTrack یک انتخاب عالی است؟

  • امنیت بالا: جنگو خودش مراقب است که کسی نتواند با دستکاری آدرس URL، به داده‌های غیرمجاز دسترسی پیدا کند.
  • کدنویسی تمیز: به جای اینکه ۱۰ خط کد بنویسید تا دستی دیتابیس را چک کنید و خطاها را مدیریت کنید، فقط با ۳ متغیر ساده، کار را تمام کردید.
  • بهینه‌سازی سئو: این ویو به راحتی با "Slug" (آدرس‌های متنی خوانا برای گوگل) سازگار می‌شود. مثلاً به جای id=5 آدرس می‌تواند python-developer-job باشد که گوگل عاشق آن است.

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

 

چرا برای آگهی‌های JobTrack از DetailView استفاده کنیم؟

در سال ۲۰۲۶، موتورهای جستجو به صفحاتی که اطلاعات دقیق و متمرکز ارائه می‌دهند، اهمیت زیادی می‌دهند. استفاده از DetailView مزایای زیر را دارد:

  • مدیریت خطای ۴۰۴ خودکار: اگر کاربر آدرس آگهی‌ای را بزند که وجود ندارد، جنگو به صورت خودکار خطای ۴۰۴ استاندارد را برمی‌گرداند.
  • ساختار URL بهینه: این ویو به خوبی با اسلاگ‌ها (Slugs) هماهنگ می‌شود که برای سئو صفحات آگهی بسیار حیاتی است.
  • خوانایی محتوا: با تمرکز روی یک شیء واحد، تمام جزئیات مثل شرایط احراز، حقوق و اطلاعات تماس شرکت بدون تداخل با بقیه داده‌ها نمایش داده می‌شود.

فایده و تاثیر این بخش:

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

امنیت در دسترسی: جنگو خودش مراقب است که داده‌های اشتباه یا مخرب از طریق URL وارد منطق برنامه نشود.

تجربه کاربری روان: سرعت بالای بارگذاری صفحه جزئیات، نرخ پرش (Bounce Rate) کاربران شما را کاهش می‌دهد.

حالا که صفحات لیست و جزئیات آماده هستند، یک سوال پیش می‌آید: چطور داده‌های جانبی (مثل لیست دسته‌بندی‌ها در کنار صفحه آگهی) را به این ویوهای آماده اضافه کنیم؟ در بخش پایانی، یاد می‌گیریم چطور با get_context_data کانتکست ویوها را غنی‌تر کنیم. آماده‌اید؟

ارسال داده‌های اضافی به قالب با get_context_data

ویوهای کلاس‌محور مثل ListView یا DetailView به صورت پیش‌فرض فقط داده‌های مربوط به همان مدل اصلی را به قالب می‌فرستند. اما در دنیای واقعی و پروژه‌ای مثل JobTrack، شما به ندرت صفحه‌ای دارید که فقط یک لیست خشک و خالی باشد. احتمالاً می‌خواهید در کنار آگهی‌ها، لیست دسته‌بندی‌ها، تعداد کل کاربران یا حتی بنرهای تبلیغاتی را هم نمایش دهید. اینجاست که متد get_context_data در جنگو به فرشته نجات شما تبدیل می‌شود.

باز کردن چمدانِ کانتکست (Context)

هر چیزی که از ویو به سمت فایل HTML می‌رود، درون یک دیکشنری به نام "کانتکست" قرار دارد. وقتی از کلاس‌های آماده استفاده می‌کنید، جنگو خودش این چمدان را با مدل اصلی پر می‌کند. برای اینکه وسایل بیشتری (داده‌های اضافی) درون این چمدان بگذارید، باید متد get_context_data را بازنویسی یا Override کنید.

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

from .models import Job, Category

class JobListView(ListView):
    model = Job
    template_name = 'jobs/job_list.html'

    def get_context_data(self, **kwargs):
        # ابتدا داده‌های پیش‌فرض (لیست آگهی‌ها) را می‌گیریم
        context = super().get_context_data(**kwargs)
        # حالا لیست تمام دسته‌بندی‌ها را هم به چمدان اضافه می‌کنیم
        context['categories'] = Category.objects.all()
        return context

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

در ادامه، هر خط را با جزئیات کامل و به زبان ساده بررسی می‌کنیم:

۱. فراخوانی مدل‌ها (Importing Models)

from .models import Job, Category

در اولین قدم، ما ابزارهای کارمان را معرفی می‌کنیم. نقطه (.) به معنی «همین‌جا» است. یعنی از فایل models.py که در همین پوشه قرار دارد، مدل Job (برای آگهی‌ها) و مدل Category (برای دسته‌بندی‌ها) را وارد می‌کنیم تا بتوانیم از آن‌ها در ویو استفاده کنیم.

۲. تعریف کلاس و انتخاب مدل اصلی

class JobListView(ListView):
    model = Job

اینجا ما از ListView ارث‌بری کرده‌ایم. با نوشتن model = Job به جنگو می‌گوییم: «هدف اصلی این صفحه، نمایش لیستِ شغل‌هاست.» جنگو هم به صورت خودکار تمام آگهی‌ها را از دیتابیس می‌کشد و آماده می‌کند.

۳. تعیین ویترین یا همان Template

template_name = 'jobs/job_list.html'

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

۴. جادوی متد get_context_data

این بخش حساس‌ترین قسمت کد است که اجازه می‌دهد داده‌های اضافه ارسال کنیم:

خط اول (تعریف متد):

def get_context_data(self, **kwargs):

ما این متد را بازنویسی می‌کنیم تا چمدانِ اطلاعات (Context) را قبل از فرستادن به صفحه، باز کنیم و چیزهای جدیدی درونش بگذاریم.

خط دوم (احترام به بزرگتر!):

context = super().get_context_data(**kwargs)

کلمه super() یعنی اول برو و تمام کارهایی که خودِ جنگو به صورت پیش‌فرض انجام می‌داد (مثل گرفتن لیست آگهی‌ها) را انجام بده و نتیجه را در متغیر context بریز. اگر این خط را ننویسیم، لیست آگهی‌های ما پاک می‌شود!

خط سوم (اضافه کردن داده جدید):

context['categories'] = Category.objects.all()

اینجا دقیقاً همان جایی است که ما دست به کار می‌شویم. ما یک کلید جدید به نام categories در چمدان می‌سازیم و تمامِ دسته‌بندی‌های موجود در دیتابیس را درون آن می‌ریزیم. حالا در فایل HTML، علاوه بر آگهی‌ها، به لیست دسته‌بندی‌ها هم دسترسی داریم.

خط چهارم (بستن و فرستادن چمدان):

return context

در نهایت، چمدانِ غنی‌شده و پر از اطلاعات را برمی‌گردانیم تا جنگو آن را به سمت مرورگر کاربر ارسال کند.

یک نکته حرفه‌ای برای مدیریت حافظه

حواستان باشد که در متد get_context_data زیاده‌روی نکنید. فراخوانی صدها مدل و داده سنگین در هر بار لود صفحه، می‌تواند سرعت سایت را کاهش دهد. همیشه فقط داده‌هایی را اضافه کنید که کاربر واقعاً در آن صفحه به آن‌ها نیاز دارد. برای داده‌های ثابت و همیشگی در تمام صفحات، راه‌های بهتری مثل "Context Processors" وجود دارد که در درس های آینده به آن می‌رسیم.

ارزش این بخش برای شما ایجاد میکند:

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

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

آمادگی برای پروژه‌های پیچیده: حالا می‌توانید داشبوردهای مدیریتی بسازید که آمار و ارقام مختلف را همزمان نشان می‌دهند.

تبریک! شما حالا استادِ جابه‌جایی داده‌ها بین دیتابیس و ویو هستید. حالا که منطقِ کار (Views) آماده است، وقت آن رسیده که به سراغ درس بعدی: تمپلیت‌ها (Templates) برویم. موافقید یاد بگیریم چطور این داده‌های خام را در یک ظاهر شیک و کاربرپسند با HTML و CSS نمایش دهیم؟