نمایش داده‌ها در تمپلیت


پس از تعریف مدل‌ها و ایجاد روابط بین آن‌ها — مانند ForeignKey، OneToOneField یا ManyToManyField — نوبت به نمایش داده‌ها در رابط کاربری می‌رسد. این مرحله در الگوی CRUD با عنوان عملیات Read شناخته می‌شود، چرا که هدف آن بازیابی و نمایش اطلاعات ذخیره‌شده در پایگاه‌داده است. در Django، این فرآیند معمولاً با ترکیب QuerySetها برای استخراج داده و Viewها برای ارسال آن‌ها به تمپلیت‌ها پیاده‌سازی می‌شود.

اصطلاح CRUD مخفف چهار عملیات پایه‌ای «ایجاد» (Create)، «خواندن» (Read)، «به‌روزرسانی» (Update) و «حذف» (Delete) است و هسته اصلی تعامل هر سامانه نرم‌افزاری با داده‌ها محسوب می‌شود. این چهار عملیات چارچوبی استاندارد برای مدیریت چرخه حیات داده‌ها در پایگاه‌های اطلاعاتی فراهم می‌کنند و در تقریباً تمام اپلیکیشن‌های تعاملی — از سیستم‌های مدیریت محتوا گرفته تا شبکه‌های اجتماعی و فروشگاه‌های آنلاین — به‌کار گرفته می‌شوند. هر بار که کاربری داده‌ای را وارد می‌کند، آن را مشاهده می‌کند، ویرایش می‌کند یا پاک می‌کند، در واقع یکی از عملیات CRUD را اجرا کرده است.

در میان این چهار عملیات، بخش Read نقشی حیاتی دارد؛ زیرا بدون آن، هیچ داده‌ای برای کاربر قابل مشاهده نخواهد بود. حتی اگر اطلاعات به‌درستی در پایگاه‌داده ذخیره شده باشند، تا زمانی که خوانده و به رابط کاربری ارسال نشوند، عملا وجود خارجی برای کاربر ندارند. هدف عملیات Read، دریافت داده‌های ذخیره‌شده در مدل‌ها و نمایش آن‌ها در تمپلیت برای کاربر نهایی است. بخش «ارسال داده‌ها به تمپلیت» در واقع قلب تپنده عملیات Read محسوب می‌شود؛ چرا که بدون این مرحله، حتی اگر داده‌ها با موفقیت از دیتابیس بازیابی شوند، کاربر هرگز آن‌ها را مشاهده نخواهد کرد.

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

  1. استخراج داده‌ها در View با استفاده از QuerySetها
  2. ارسال داده‌ها به تمپلیت از طریق یک دیکشنری به نام context

  3. نمایش داده‌ها در HTML Template با کمک تگ‌ها، متغیرها و فیلترهای زبان تمپلیت جنگو

برای پیاده‌سازی این فرآیند، ابتدا باید داده‌های مدل — از جمله روابط معکوس (reverse relationships) — را در View بازیابی کرد. سپس این داده‌ها را در قالب یک دیکشنری (context) به تمپلیت ارسال نمود. در نهایت، در خود تمپلیت، با بهره‌گیری ازقابلیت‌های زبان تمپلیت جنگو — شامل متغیرها (Variables)، فیلترها (Filters) و تگ‌های تمپلیت (Template Tags) — داده‌ها به‌صورت مناسب نمایش داده می‌شوند.

 

در اینجا قصد داریم لیست تمام پروژه‌های تعریف‌شده در مدل Project را در مسیر /projects/ نمایش دهیم، به‌طوری که با انتخاب عنوان هر پروژه، کاربر به صفحه جزئیات آن (در مسیر /read-project/) هدایت شود.

 

جمع‌آوری داده‌ها در View


ابتدا در فایل views.py، یک تابع برای بازیابی تمام رکوردهای مدل Project و ارسال آن‌ها به تمپلیت تعریف می‌کنیم

coreapp/views.py

from . import models

def Projects(request):
  projectObjs = models.Project.objects.all()
  context = {'projects':projectObjs}
  return render(request, 'projects.html', context)
    • متد objects.all() تمامی رکوردهای مدل Project را از پایگاه داده واکشی می‌کند.
    • داده‌ها درون یک دیکشنری با کلید 'projects' قرار گرفته و به تمپلیت ارسال می‌شوند.

 

تعریف الگوی URL


پس از ایجاد تابع view، نیاز است مسیر مربوطه را در فایل urls.py ثبت کنیم تا درخواست‌های ارسالی به /projects/ به تابع View مربوطه هدایت شوند.

coreapp/urls.py

urlpatterns = [
    ... ,
    path('projects/', views.Projects, name='Projects'),
    ... ,
]

 

نمایش داده‌ها در تمپلیت


در نهایت، در فایل تمپلیت projects.html، لیستی از عناوین پروژه‌ها را با استفاده از حلقهٔ {% for %} نمایش خواهیم داد.

coreapp/templates/projects.html

{% extends 'base.html' %}
{% block title %} {{ block.super}} | Projects {% endblock %}
{% block content %}
  <h1>Projects List</h1>
  <ul>
    {% for project in projects %}
    <li> {{ project.title }} </li>
    {% empty %}
      <li>No Project Found</li>
    {% endfor %}
  </ul>
{% endblock %}
💡 استفاده از تگ {% empty %} در حلقه‌ها، روشی تمیز برای نمایش پیام جایگزین در صورت عدم وجود داده است.

در ننیجه با مراجعه به مسیر آدرس  http://127.0.0.1:8000/projects/ لیستی از تمامی پروژه‌ها به نمایش درخواهد آمد.

این پیاده‌سازی، نمونه‌ای کلاسیک از عملیات Read در الگوی CRUD است. داده‌ها از دیتابیس خوانده شده، به تمپلیت ارسال گشته و به‌صورت کاربرپسند نمایش داده می‌شوند — همان‌گونه که کاربران انتظار دارند.

 

نمایش جزئیات هر پروژه (Read Details)


حال، طبق شرحی که داده شد بنا داریم فرایند را تکمیل کنیم، به‌گونه‌ای که با کلیک روی عنوان هر پروژه ، کاربر به صفحه جزئیات آن هدایت شود. برای این منظور، ابتدا یک تابع View جدید برای نمایش جزئیات پروژه تعریف می‌کنیم.

coreapp/views.py

from . import models

def ProjectRead(request, uid):
  projectObj = models.Project.objects.get(id = uid)
  context = {'project': projectObj}
  return render(request, 'project-read.html', context)
    • پارامتر uid مقداری است که از آدرس URL دریافت می‌شود (در ادامه توضیح خواهیم داد چگونه).
    • متد get(id=uid) رکورد مربوط به آن شناسه را از مدل Project واکشی می‌کند.
    • داده‌ی واکشی‌شده در متغیر context قرار می‌گیرد و برای نمایش در تمپلیت، ارسال می‌گردد.

 

پس از ایجاد تابع view، نیاز است مسیر مربوطه را نیز در فایل urls.py ثبت کنیم تا درخواست کاربر به درستی هدایت شود.

coreapp/urls.py

urlpatterns = [
    ... ,
    path('project-read/<str:uid>/', views.ProjectRead, name='ProjectRead'),
    ... ,
]
    • project-read/<str:uid>/ — شکلی پویا (Dynamic) دارد.
    • <str:uid> بخش متغیر مسیر است.
    • پیشوند str: تعیین می‌کند که نوع داده‌ی ورودی، رشته (string) باشد.
    • نام uid همان کلیدی است که مقدار دریافتی از URL را به View ارسال می‌کند.

 

در نتیجه تابع ProjectRead() دقیقا می‌داند باید کدام پروژه را از پایگاه‌داده واکشی کند.

🔸 دلیل اینکه مسیر را به این شکل (<str:uid>) تعریف نمودیم این است که شناسه‌ی هر پروژه معمولا به‌صورت رشته‌ی یکتا (UUID) در مدل ذخیره می‌شود. بنابراین باید نوع داده‌ی ورودی را str تعریف کنیم تا جنگو بتواند مقدار UUID را به‌درستی دریافت و پردازش کند.

به‌عبارت دیگر، با این ساختار:

    • می‌توان به هر پروژه از طریق آدرس منحصربه‌فردش دسترسی پیدا نمود.
    • مسیرها خواناتر و استانداردتر می‌شوند.
    • عملیات بازیابی داده‌ها در View ساده‌تر و مستقیم‌تر انجام می‌گیرد.

 

در مرحله پایانی، تمپلیت project-read.html با دریافت اطلاعات پروژه از view، داده‌ها — مانند عنوان، حوزه کاری، تگ‌ها و توضیحات — را به‌شکل ساختارمند و قابل‌درک در رابط کاربری به نمایش درمی‌آورد. 

coreapp/templates/project-read.html

{% extends 'base.html' %}

{% block title %} {{ block.super}} | {{ project.title }} {% endblock %}

{% block content %}

  <h1> {{ project.title }} </h1>
  <h3> Project Area 🡢 {{ project.area }} </h3>

  <hr align="left" width="20%">

  <p> Technologies 🡢 
    {% for tag in project.tags.all %}
      <strong> #{{ tag.name }}{% if not forloop.last %},{% endif %} </strong>
    {% endfor %}
  </p>

  <hr align="left" width="20%">

  <p>{{ project.content|linebreaksbr }}</p>

{% endblock %}
  • از {{ project.field_name }} برای دسترسی به فیلدهای پروژه استفاده می‌گردد.

  • حلقه‌ی for تگ‌های مرتبط را نمایش می‌دهد.

  • فیلتر linebreaksbr خطوط متن را به <br> در HTML تبدیل می‌کند تا متن خواناتر شود.

 

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

coreapp/templates/projects.html

{% extends 'base.html' %}
{% block title %} {{ block.super}} | Projects {% endblock %}
{% block content %}
  <h1>Projects List</h1>
  <ul>
    {% for project in projects %}
    <li> 
      <a href="{% url "ProjectRead" project.id %}">{{ project.title }} </a> <!-- Define Redirected Links -->
    </li> 
    {% endfor %}
  </ul>
{% endblock %}

حال در صورت انتخاب عنوان هر پروژه در مسیر آدرس /projects/، کاربر به صفحه جزئیات آن (در مسیر /read-project/<id>) هدایت خواهد شد.

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