مكان الـ Template في Django MVT
Model View Template — مين بيعمل إيه؟
Django مبني على نمط MVT: الـ Model مسؤول عن البيانات، الـ View مسؤول عن استقبال الـ
Request وتجهيز البيانات، والـ Template مسؤول عن شكل العرض النهائي للمستخدم.
Template هو أقرب جزء للـ presentation layer. الـ View في Django مش هو شاشة العرض؛ هو Python function/class بيربط الطلب بالبيانات والـ template.Model
بيمثل البيانات وقواعد التعامل مع الـ Database.
View
بيستقبل الـ Request، يجهز البيانات، ويرجع HttpResponse غالبا عن طريق render().
Template
ملف HTML فيه Django Template Language عشان يعرض البيانات بشكل Dynamic.
Static HTML vs Dynamic Template
ليه أصلا محتاجين Templates؟
- المحتوى مكتوب ثابت داخل الملف.
- لو فتحت الصفحة 100 مرة هتشوف نفس الكلام.
- مناسب لصفحة بسيطة جدا، لكنه ضعيف مع Student Portal أو E-commerce.
- لو عندك 100 طالب، مش منطقي تعمل 100 ملف HTML.
- HTML عادي لكن فيه placeholders زي
{{ student_name }}. - بيستقبل values من الـ
Viewمن خلالcontext dictionary. - يقدر يعمل loop على قائمة records.
- يقدر يظهر أو يخفي أجزاء باستخدام
{% if %}.
المتصفح عمره ما بيشوف {{ name }} أو {% for %} كـ Django syntax. الـ Template بيتعمله processing على
الـ Server، وبعدها المتصفح يستلم HTML جاهز.
<h1>Welcome Mona</h1>
<p>Your academic level is 2</p>
Where Do We Store Templates?
تنظيم الملفات قبل ما الصفحة تكبر
الطريقة الشائعة والأكثر أمانا هي إن كل app يبقى جواه folder اسمه templates، وجواه folder باسم الـ app نفسه.
السبب: لو عندك أكتر من app وفيهم ملف اسمه list.html، Django ممكن يتلخبط بين الملفات.
students/
templates/
students/
home.html
list.html
profile.html
students/templates/students/list.html أحسن من templates/list.html داخل app، لأنه بيمنع name collisions بين التطبيقات.
أحيانا بنعمل folder عام اسمه templates على مستوى المشروع كله. وقتها لازم نضيفه في إعدادات TEMPLATES
داخل settings.py.
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
django-admin startproject، Django مش بيعمل لك templates file/folder جاهز تلقائيا؛ أنت اللي بتنظمه حسب مشروعك.Using render() and URL Flow
إزاي الـ View يرجع Template؟
ملف الـ Template في البداية ممكن يكون HTML عادي جدا. الديناميكية هتيجي لما الـ View يبعتله data.
<!DOCTYPE html>
<html>
<head>
<title>Students Home</title>
</head>
<body>
<h1>Welcome to the Students App</h1>
<p>This page is rendered by Django.</p>
</body>
</html>
دالة render() بتاخد request واسم الـ template، وترجع HttpResponse جاهز.
from django.shortcuts import render
def home(request):
return render(request, 'students/home.html')
الـ URLconf هو اللي بيستقبل path من المتصفح ويقرر أي View يتنفذ.
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
]
Request → URLconf → View → Template → Response.Context and Template Variables
إرسال values من Python إلى HTML
الـ context هو dictionary: الـ keys هي الأسماء اللي هتستخدمها داخل الـ Template، والـ values هي البيانات الحقيقية.
في الـ Template بنطبع قيمة variable باستخدام double curly braces: {{ variable_name }}.
from django.shortcuts import render
def welcome(request):
context = {
'student_name': 'Ali',
'level': 2,
}
return render(request, 'students/welcome.html', context)
<h1>Welcome {{ student_name }}</h1>
<p>Your academic level is {{ level }}</p>
- اسم الـ variable داخل template لازم يطابق key موجود في الـ
context dictionary. - لو variable مش موجود، Django غالبا يعرض empty output بدل ما يطبع error واضح في الصفحة.
- ممكن تبعت String أو Number أو List أو Object أو Model Instance.
- الـ Template بيعرض البيانات، لكن الحسابات الثقيلة وقرارات الـ business logic مكانها الـ
ViewأوModel.
'student_name' في الـ context هو اللي بيظهر في HTML كـ {{ student_name }}. اسم Python variable نفسه مش شرط يكون هو نفس الاسم.
Lists, for Loops, and empty
عرض records كتير بدل قيمة واحدة
معظم الصفحات الواقعية بتعرض list: courses, students, messages, notifications, comments. بنبعت الـ list في context عادي،
وبعدها نستخدم {% for %} جوه الـ Template.
def course_list(request):
courses = ['Python', 'Database', 'AI', 'Networks']
return render(request, 'students/courses.html', {'courses': courses})
<h2>Registered Courses</h2>
<ul>
{% for course in courses %}
<li>{{ course }}</li>
{% endfor %}
</ul>
الـ block بين {% for %} و{% endfor %} بيتكرر مرة لكل item في الـ list.
<h2>Registered Courses</h2>
{% if courses %}
<ul>
{% for course in courses %}
<li>{{ course }}</li>
{% endfor %}
</ul>
{% else %}
<p>No courses found.</p>
{% endif %}
داخل for في Django تقدر تستخدم {% empty %} كـ fallback لو الـ list فاضية.
<ul>
{% for course in courses %}
<li>{{ course }}</li>
{% empty %}
<li>No courses found.</li>
{% endfor %}
</ul>
{% for x in y %}، ولازم تقفله بـ {% endfor %}.if Tag and Template Logic
إظهار أو إخفاء أجزاء من الصفحة
الـ {% if %} بيخلي الـ Template يعرض HTML معين حسب condition. ممكن تستخدم {% elif %} و{% else %}،
ولازم تقفل بـ {% endif %}.
<h2>Student Result</h2>
{% if mark >= 50 %}
<p>Passed</p>
{% else %}
<p>Failed</p>
{% endif %}
| Good in the View | Good in the Template |
|---|---|
| Database queries | Display variables |
| Complex calculations | Simple display conditions |
| Business rules | Loops for rendering lists |
| Preparing context data | Formatting output with filters |
Objects, Dot Notation, and Filters
عرض attributes وتنسيق القيم
لو بعتت object أو Model Instance باسم student، تقدر توصل للـ attributes باستخدام dot notation:
{{ student.name }}. Django Template Language بيسهل الوصول للبيانات بدون Python parentheses.
<h2>Student Profile</h2>
<p>Name: {{ student.name }}</p>
<p>Level: {{ student.level }}</p>
<p>Department: {{ student.department }}</p>
<ul>
{% for student in students %}
<li>{{ student.name }} - Level {{ student.level }}</li>
{% endfor %}
</ul>
كل iteration بيطلع object واحد من students، وتقدر تعرض attributes بتاعته.
الـ Filter بيغير طريقة عرض القيمة فقط، من غير ما يغير البيانات الأصلية. syntax بتاعه هو pipe:
{{ value|filter }}.
| Filter | Example | Use |
|---|---|---|
upper | {{ name|upper }} | تحويل النص لـ uppercase. |
lower | {{ name|lower }} | تحويل النص لـ lowercase. |
title | {{ department|title }} | أول حرف من كل كلمة capital. |
length | {{ students|length }} | عدد الحروف أو عناصر list. |
default | {{ email|default:"No email" }} | fallback لو القيمة empty. |
truncatechars | {{ text|truncatechars:20 }} | اختصار النص بعد عدد characters. |
date | {{ created_at|date:"Y-m-d" }} | تنسيق التاريخ. |
join | {{ courses|join:", " }} | دمج عناصر list في string. |
safe | {{ content|safe }} | اعتبار المحتوى HTML آمن، ويستخدم بحذر شديد. |
escape | {{ content|escape }} | منع HTML rendering وعرضه كنص. |
safe مع user input غير موثوق؛ ممكن يفتح باب XSS. الافتراضي في Django هو escaping لحماية الصفحة.Template Inheritance and include
تقليل التكرار وبناء layout قابل لإعادة الاستخدام
لو كل صفحة فيها نفس navbar وfooter وHTML structure، أي تعديل بسيط هيتكرر في كل الملفات.
Django بيحل المشكلة بـ template inheritance: ملف parent اسمه غالبا base.html، وصفحات child بتعمل
{% extends %} وتملأ blocks.
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Students App{% endblock %}</title>
</head>
<body>
<header>Students Portal</header>
{% block content %}
{% endblock %}
<footer>Faculty of Computers and AI</footer>
</body>
</html>
{% extends 'students/base.html' %}
{% block title %}Courses{% endblock %}
{% block content %}
<h2>Registered Courses</h2>
<p>This content replaces the content block.</p>
{% endblock %}
- استخدم أسماء blocks واضحة زي
title,content,sidebar,scripts. - حط
{% extends %}في أعلى child template. - خلي
base.htmlعام وقابل لإعادة الاستخدام، من غير تفاصيل page-specific. - أي content خارج blocks في child غالبا مش هيظهر بالطريقة اللي متوقعها.
{% include %} بيستخدم لما تحب تدخل template صغير جوه template تانية، زي navbar.html أو
alert.html أو student_card.html. الفرق: extends لهيكل الصفحة الكامل، وinclude لقطعة صغيرة قابلة لإعادة الاستخدام.
<body>
{% include 'students/navbar.html' %}
{% block content %}{% endblock %}
</body>
Static Files, url Tag, and csrf_token
إكمال بناء الصفحة الحقيقية
الـ Static files زي CSS, JavaScript, images مش بنكتب path كامل من جهازنا. بنستخدم نظام Django static:
أول حاجة {% load static %}، وبعدها {% static 'path/file.css' %}.
{% load static %}
<link rel="stylesheet" href="{% static 'students/css/style.css' %}">
<img src="{% static 'students/images/logo.png' %}" alt="Logo">
{% load static %} قبل استخدام {% static %}.{% url %} بيستخدم route name من urls.py بدل hard-coded path. لو path اتغير واسم route ثابت، اللينك يفضل شغال.
<a href="{% url 'home' %}">Home</a>
<a href="{% url 'student_list' %}">Students</a>
<a href="{% url 'student_detail' student.id %}">View Profile</a>
أي form في Django يستخدم POST غالبا لازم يحتوي على {% csrf_token %} للحماية من
Cross-Site Request Forgery.
<form method="post">
{% csrf_token %}
<input type="text" name="name">
<button type="submit">Save</button>
</form>
| Tag | الغرض | مثال |
|---|---|---|
{% extends %} | يرث من parent template. | {% extends 'base.html' %} |
{% block %} | يحدد جزء child template يقدر يغيره. | {% block content %} |
{% include %} | يدخل template صغيرة داخل أخرى. | {% include 'navbar.html' %} |
{% if %} | condition لعرض HTML معين. | {% if user.is_authenticated %} |
{% for %} | loop على list أو QuerySet. | {% for student in students %} |
{% empty %} | ينفذ لو loop list فاضية. | {% empty %} |
{% load static %} | تحميل static template library. | {% load static %} |
{% url %} | يبني URL من route name. | {% url 'home' %} |
{% csrf_token %} | حماية POST forms. | {% csrf_token %} |
{# comment #} | تعليق لا يظهر في الـ rendered output. | {# hidden note #} |
Mini Project: Student List Page
تطبيق عملي يجمع render + context + loop + inheritance
هنفترض إن عندنا صفحة تعرض list of student dictionaries. لاحقا في محاضرات الـ Models، نفس الفكرة هتيجي من Database بدل hard-coded list.
students list ويبعته كـ context.student_list.from django.shortcuts import render
def student_list(request):
students = [
{'name': 'Ali', 'level': 2},
{'name': 'Mona', 'level': 2},
{'name': 'Omar', 'level': 3},
]
return render(request, 'students/list.html', {'students': students})
{% extends 'students/base.html' %}
{% block title %}Students{% endblock %}
{% block content %}
<h2>Students List</h2>
<ul>
{% for student in students %}
<li>{{ student.name }} - Level {{ student.level }}</li>
{% empty %}
<li>No students found.</li>
{% endfor %}
</ul>
{% endblock %}
الـ CSS بيحسن شكل العرض، لكنه مش بيخلي الصفحة Dynamic لوحده. الديناميكية جاية من Django rendering والـ context.
body{
font-family: Arial, sans-serif;
}
li{
margin-bottom: 8px;
padding: 6px;
background-color: #f4f7fb;
}
Common Errors, Debugging, and Best Practices
أغلب مشاكل الـ Templates صغيرة لكن بتوقف الصفحة
| Error | السبب المعتاد | راجع إيه؟ |
|---|---|---|
TemplateDoesNotExist | path غلط أو الملف في folder غلط. | templates/app_name/file.html وTEMPLATES settings. |
| Empty output | variable مش موجود في context. | أسماء keys في context dictionary. |
| TemplateSyntaxError | ناقص %} أو }} أو closing tag. | {% endfor %}, {% endif %}, {% endblock %}. |
| Static file not loading | نسيان {% load static %} أو path غلط. | static folder structure وtemplate tag. |
NoReverseMatch | {% url %} باسم route غلط أو parameters ناقصة. | urls.py route name والـ arguments المطلوبة. |
المثال ده فيه missing brace وunclosed tag. دي أخطاء واقعية جدا في اللاب.
<ul>
{% for student in students %}
<li>{{ student.name } - Level {{ student.level }}</li>
{% endfor %
</ul>
<ul>
{% for student in students %}
<li>{{ student.name }} - Level {{ student.level }}</li>
{% endfor %}
</ul>
- ابدأ بالـ template path في
render(). - راجع folder structure: app/templates/app/file.html.
- اطبع أو راجع context keys في الـ
View. - اقرأ traceback؛ غالبا هيقولك اسم الملف والسطر.
- اختبر بنسخة أبسط من الـ Template لو المشكلة مش واضحة.
- استخدم variable names واضحة:
student_name,course_list,total_marks. - استخدم
inheritanceبدل copy-paste للـ layout. - استخدم
includeللقطع الصغيرة المتكررة. - خلي الـ Template بسيط، والـ View يجهز البيانات.
- شغل
python manage.py runserverوجرب صفحة واحدة في كل مرة.
Lecture 07 — Exam Questions
أسئلة من امتحانات 2021 و2024 و2025، مرتبة حسب ترتيب الشرح.
Django بيستخدم
Model View Template. وده مهم جدا في المحاضرة دي لأن الـ Template هو جزء العرض اللي بيستقبل data من الـ View.
في Django MVT، الـ
Template هو الأقرب للـ presentation layer. الـ View بيستقبل request ويجهز context ويختار template.
architecture بتاعة Django بتجمع
Models وViews وTemplates. المحاضرة دي مركزة على الـ Templates ودورها في عرض البيانات.
django-admin startproject بيعمل ملفات المشروع الأساسية زي settings.py وurls.py، لكن مش بيعمل template file تلقائيا. أنت بتنظم templates folder بنفسك.
{{ name }} mean in Django Templates?{{ name }} معناها إن Django هيستبدل placeholder بقيمة name القادمة من الـ context. المتصفح يستلم القيمة النهائية، مش الـ Django syntax.
{% for x in y %}الـ
for في Django Template Tag بيتكتب بين {% و%}، ولازم يتقفل بـ {% endfor %}.
forloop.counterداخل Django loop تقدر تستخدم
{{ forloop.counter }} عشان تعرض رقم iteration يبدأ من 1. مفيش parentheses في template variable؛ يعني نكتب forloop.counter مش forloop.counter().