Project vs App — الفرق بين المشروع والتطبيق
فكّر في الـ Project كالجامعة كاملها، والـ App كـ كلية واحدة جوّاها
📁 Django Project
- الإعدادات العامة للـ Server (settings.py)
- ملف الـ URLs الرئيسي (urls.py)
- يحتوي على عدة Apps مختلفة
- بيُنشأ بأمر:
django-admin startproject - Configuration واحدة للكل
📦 Django App
- وحدة قائمة بذاتها مسؤولة عن Feature معين
- ليها Views, URLs, Models, Templates خاصة بيها
- ممكن تتعاد استخدام في Project تاني (Reusable)
- بتُنشأ بأمر:
python manage.py startapp - أمثلة: students, courses, accounts, library
Creating & Setting Up a Django App — إنشاء وإعداد App
الخطوات من الأمر للتسجيل للشغل
python manage.py startapp students
الأمر ده بيعمل مجلد جديد اسمه students جوّاه ملفات جاهزة تلقائياً.
| الملف | دوره | حالة استخدامه |
|---|---|---|
views.py | تعريف الـ View Functions | مهم جداً |
models.py | تعريف جداول قاعدة البيانات | مهم جداً |
admin.py | تسجيل الـ Models في الـ Admin Panel | مهم |
apps.py | Configuration class للـ App | متوسط |
urls.py | URL Patterns خاصة بالـ App (يتعمل يدوياً) | مهم جداً |
migrations/ | سجل تغييرات الـ Database | مهم |
تسجيل الـ App في settings.py — INSTALLED_APPS
بدون التسجيل، Django مش بيعرف إن الـ App موجودة أصلاً
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'students', # ← الـ App اللي أنشأناها
]
INSTALLED_APPS، الـ Templates مش هتتاكتشف، والـ Models مش هتشتغل، والـ Admin مش هيشوفها. دايماً سجّل الـ App فور ما تعملها!| المشكلة | السبب |
|---|---|
| Templates غير موجودة في الـ Discovery | Django مش بيفتش جوّا الـ App عشان مش عارف بيها |
| Admin مش بيشوف الـ Models | Admin Registration بيحتاج App مسجّلة أولاً |
| Migrations مش بتشتغل صح | الـ App نفسها مش معروفة |
URL Dispatcher — كيف الـ Request يوصل للـ View
الرحلة الكاملة من المتصفح للكود Python
الـ URL Dispatcher هو الـ Component اللي بيمبّط أي URL قادم على الـ Server لـ View Function معينة. بيقرأ الـ URL، بيقارنه بالـ URL Patterns المعرّفة، ولو لقى Match بيودّي الـ Request للـ View المناسبة.
Project URLs & App URLs — مستويات الـ Routing
ليه في مستويين؟ وإيه الفرق؟
ملف urls.py الرئيسي في مجلد الـ Project هو نقطة الدخول لكل الـ Requests. بيعمل حاجتين:
- بيضيف مسار الـ Admin Panel
- بيحوّل الـ Requests للـ Apps المختلفة باستخدام
include()
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('students/', include('students.urls')), # ← يحوّل كل /students/* للـ App path('courses/', include('courses.urls')), # ← يحوّل كل /courses/* للـ App ]
- ملف الـ Project يفضل قصير وبسيط — مش هيحمل كل URLs الموقع
- كل App بتتولى الـ URLs الداخلية بتاعتها
- Apps جديدة ممكن تتضاف بسطر واحد بس
- Debugging أسهل بكتير
الملف ده بتعمله إنت يدوياً جوّا مجلد الـ App. بيحدد الـ URLs الداخلية للـ App وكل واحدة بتوصّل لإنهي View.
from django.urls import path from . import views # ← import الـ views من نفس المجلد urlpatterns = [ path('', views.home, name='home'), # /students/ path('about/', views.about, name='about'), # /students/about/ path('contact/', views.contact, name='contact'), # /students/contact/ ]
- الأول: الـ Route String — المسار مثل
'about/' - الثاني: الـ View Function — مثل
views.about - الثالث (اختياري):
name=— اسم للـ URL للاستخدام في الـ Templates لاحقاً
الـ Full URL = الـ Prefix من Project urls + الـ Path من App urls
| Project Prefix | App Path | الـ Full URL |
|---|---|---|
students/ | '' (فاضي) | /students/ |
students/ | about/ | /students/about/ |
students/ | contact/ | /students/contact/ |
courses/ | list/ | /courses/list/ |
/ في النهاية). خلّي أسلوبك ثابت في المشروع كله — إما بنهاية slash أو بدونها.- Django بيفحص الـ Patterns من فوق لتحت — أول Match يفوز
- حط الـ Patterns الأكثر تحديداً (Specific) قبل الـ Broad ones
- الـ Pattern العام (catch-all) لازم يكون آخر حاجة
urlpatterns = [
path('student/<int:id>/', views.student_detail), # أكثر تحديداً — أول
path('student/', views.students_list), # أقل تحديداً — تاني
path('', views.home), # Catch-all — آخر
]
Dynamic URL Parameters — قيم متغيرة في الـ URL
إزاي تمرّر قيم مثل ID أو اسم في الـ URL للـ View
ممكن تضمّن قيم متغيرة في الـ URL Pattern باستخدام <type:name> — وDE القيمة بتوصل للـ View كـ Argument تلقائياً.
urlpatterns = [
path('student/<int:id>/', views.student_detail), # id رقم صحيح
path('profile/<str:username>/', views.profile), # username نص
]
from django.http import HttpResponse def student_detail(request, id): # id بييجي كـ Argument return HttpResponse(f'طالب رقم: {id}') def profile(request, username): return HttpResponse(f'Profile of: {username}')
| الـ Converter | النوع | مثال |
|---|---|---|
<str:name> | نص بدون Slash | /students/ali/ |
<int:id> | رقم صحيح فقط | /students/42/ |
<slug:code> | حروف وأرقام وـ Hyphen وـ Underscore | /course/web-tech/ |
<uuid:item_id> | UUID بالصيغة الكاملة | /item/550e8400.../ |
Function-Based Views — الـ FBV
الـ View هي نقطة دخول الـ Business Logic — هنا بيتخذ القرار
الـ View في Django هو function Python عادي بيستقبل request object ولازم يرجع response object. ده بالظبط أول سطر في أي View تكتبه.
الـ View بيعمل:
- بيقرأ الـ Request (Method, Headers, Data)
- بيعمل الـ Business Logic والـ Validation
- ممكن يجيب بيانات من الـ Database
- بيختار نوع الـ Response
- بيرجع الـ Response للمتصفح
الـ View مش بيعمل:
- مش بيشتغل على الـ HTML مباشرة (للـ Template)
- مش بيتعامل مع الـ Routing (للـ urls.py)
- مش بيحفظ البيانات مباشرة (للـ Model)
from django.http import HttpResponse def home(request): return HttpResponse('Welcome to the Students App') def about(request): return HttpResponse('This is the About page') def contact(request): return HttpResponse('<h1>Contact Us</h1><p>Email: info@cu.edu.eg</p>')
from django.http import HttpResponse def home(request): return HttpResponse('Students Home Page') def contact(request): return HttpResponse('Contact the students office') def help_page(request): return HttpResponse('Help and FAQ page')
from django.urls import path from . import views urlpatterns = [ path('', views.home, name='home'), path('contact/', views.contact, name='contact'), path('help/', views.help_page, name='help'), ]
- المتصفح يفتح
/students/→ يشتغلhome() - المتصفح يفتح
/students/contact/→ يشتغلcontact() - المتصفح يفتح
/students/help/→ يشتغلhelp_page() - أي URL تاني → 404 Not Found
render() والـ Templates — الطريقة الصح
Separation of Concerns — الـ Logic هنا والـ HTML هناك
الـ render() هي الدالة المفضّلة لإرجاع HTML. بتاخد الـ request والـ Template ومتغيرات (Context) وبترجعها كـ HttpResponse.
from django.shortcuts import render def home(request): context = { 'title': 'Students Home', 'message': 'Welcome to the students portal', 'count': 250, } return render(request, 'students/home.html', context)
الـ Template Convention الموصى بيها في Django:
courses وعندها home.html كمان، Django هيتلخبط. بالاسم الكامل students/home.html مفيش لبس.<h1>{{ title }}</h1> <p>{{ message }}</p> <p>Total students: {{ count }}</p> <!-- Template Tags — Logic --> {% if count > 100 %} <span>Large class!</span> {% endif %}
{{ variable }}— عرض قيمة متغير (Variable Output){% tag %}— Template Tags — Logic (for loops, if conditions, blocks){# comment #}— تعليق لا يظهر في الـ HTML
/students/include('students.urls') بيحوّل الـ Request لـ students/urls.pypath('', views.home) تطابق، يُستدعى home(request){{ title }} وغيرها للقيم الحقيقيةJsonResponse — ردود الـ API
لما بتعمل API بدل صفحة HTML
ممكن الـ View ترجع JSON Data بدل HTML — مفيد جداً لعمل APIs. الـ JsonResponse بتحوّل الـ Python Dictionary لـ JSON تلقائياً وبتضيف الـ Content-Type الصح.
from django.http import JsonResponse def api_status(request): return JsonResponse({ 'status': 'ok', 'app': 'students', 'version': '1.0' })
from django.http import HttpResponse, JsonResponse def demo(request): if request.GET.get('format') == 'json': return JsonResponse({'page': 'demo'}) return HttpResponse('Demo page in HTML')
Debugging & Common Errors — أخطاء شائعة وحلولها
اقرأ الـ Error Messages ببطء بدل الهلع!
- افحص الـ Full URL اللي بتكتبه في المتصفح
- افحص إن Project urls فيها
include('app.urls') - افحص إن App urls فيها الـ Pattern الصح
- انتبه للـ Trailing Slash
- افحص إن الـ App مسجّلة في
INSTALLED_APPS
- افحص اسم الـ File والـ Function بدقة
- تأكد إن
from . import viewsصح في الـ App urls - تأكد إن الـ Function موجودة فعلاً في
views.py - اقرأ الـ Traceback بالكامل — الأخطاء بتدلك على السطر
# خطأ from django.urls import path # صح from django.urls import path, include
# خطأ — view بدون s path('about/', view.about) # صح path('about/', views.about)
# خطأ — اسم الـ App غلط path('students/', include('student.urls')) # مفيش s في النهاية # صح path('students/', include('students.urls'))
أسئلة امتحانات Django Apps & URLs & Views
كل الأسئلة من امتحانات 2021 + 2024 + 2025 المتعلقة بالمحاضرة دي — مرتبة حسب ترتيب الشرح 🇪🇬
Django بيستخدم نمط الـ MVT:
- Model: بنية البيانات والتعامل مع الـ Database
- View: الـ Business Logic واستقبال الـ Requests
- Template: الـ HTML وطريقة عرض البيانات
عشان يظهر الـ Model في الـ Admin Interface على
/admin/، لازم تعمل حاجتين:
- import الـ Model في
admin.py - استدعاء
admin.site.register(Student)
python manage.py createuser. (True or False?)الأمر الصح هو
python manage.py createsuperuser وليس createuser! createsuperuser هو اللي بيعمل Admin User عنده صلاحية الدخول لـ /admin/. createuser مش موجود في Django.
django start my_tennis_clubpy manage.py start-django my_tennis_clubdjango-admin startproject my_tennis_clubdjango-admin startproject my_tennis_clubده الأمر الرسمي لإنشاء Django Project جديد. بيعمل مجلد بيحتوي على
settings.py، urls.py، manage.py وغيرها تلقائياً. مقارنة: startapp لإنشاء App، startproject لإنشاء Project.
members, and a model named Member, what is the correct syntax to import the model?from members.models import Memberimport Member from membersimport members.Memberfrom members.models import Memberالـ Models في Django بتكون في ملف
models.py جوّا مجلد الـ App. لاستيراد Model معين بتكتب: from app_name.models import ModelName. الصيغة بتتبع نمط Python القياسي.
for loop?(for x in y)<% for x in y %>{% for x in y %}{% for x in y %}في Django Templates، الـ Template Tags (اللي بتعمل Logic زي loops وـ if conditions) بتُحاط بـ
{% %}. مقارنة:
{% for x in y %}— Template Tag للـ Logic{{ variable }}— عرض قيمة متغير{# comment #}— تعليق مخفي
python manage.py runmigrationspython manage.py executemigrationspython manage.py makemigrationsالأمر اللي بيخلي التغييرات تتنفذ فعلياً في الـ Database هو
python manage.py migrate وهو مش موجود في الاختيارات. makemigrations بيجهّز ملف الترحيل بس.
🇪🇬 makemigrations = خطوة 1 (بيجهّز). migrate = خطوة 2 (بيطبّق في الـ DB).
الأمر
migrate مش بيعرض التغييرات — ده بيعمل تطبيق التغييرات على الـ Database الفعلي (Creates/Alters Tables). اللي بيعرض التغييرات ويعمل migration file هو makemigrations.
الـ View في Django مش بتمثّل الـ Presentation Layer — ده الـ Template! الـ View بتمثّل الـ Business Logic Layer. الـ Template هي اللي بتتحكم في طريقة عرض البيانات (Presentation). في الـ MVT:
- Model = Data Layer
- View = Business Logic
- Template = Presentation Layer
Post.Objects.all() will retrieve all objects in the Post table. (True or False?)الكود ده غلط! الـ
Objects بـ O كبيرة غلط. الصح هو Post.objects.all() بـ o صغيرة. Python وDjango Case-Sensitive — objects (كلها صغيرة) هو الـ Manager الافتراضي، أما Objects بـ O كبيرة فمش موجود وهيطلع AttributeError.
include("students.urls")?الـ
include() بيتكتب في ملف الـ Project urls.py الرئيسي (مش App urls). بيقول للـ Django: "أي Request بييجي على /students/*، حوّله لملف students/urls.py عشان يكمّل الـ Routing جوّاه."
students/ to students.urls, and app urls contain path("about/", views.about), what is the full browser path?الـ Full URL = Project Prefix + App Path
=
students/ + about/ = /students/about/ده بالظبط إزاي Django بيركّب الـ URLs عبر المستويين.