
كيفية برمجة منصة مسابقات تفاعلية باستخدام Python Django
في عصر التعلم عن بعد والتقييم الرقمي، أصبحت منصات المسابقات والاختبارات
التفاعلية أداة قيمة للمؤسسات التعليمية والمدربين والأفراد على حد سواء.
إذا كنت تطمح لتعلم كيفية برمجة منصة مسابقات أو اختبارات تفاعلية باستخدام
Python Django، فأنت في المكان الصحيح. هذا الدليل الشامل سيأخذك
خطوة بخطوة خلال عملية إنشاء منصة ديناميكية لتقديم وإدارة الاختبارات والمسابقات.
سنتناول كل شيء بدءًا من تصميم واجهة مستخدم سهلة الاستخدام لعرض
الأسئلة وتقديم الإجابات، مرورًا بتعريف نماذج البيانات لتخزين معلومات الأسئلة
والاختيارات والإجابات، وصولًا إلى تمكين المستخدمين من تقديم إجاباتهم
و حفظ بيانات الإجابات، وحساب النتائج وعرضها، وأخيرًا نشر التطبيق ليصبح
متاحًا للاستخدام. انطلق معنا في هذه الرحلة لتعلم كيفية برمجة منصة مسابقات أو
اختبارات باستخدام Python Django بطريقة منظمة وفعالة.
خطوات برمجة منصة مسابقات باستخدام Python Django
الخطوة 1: إعداد بيئة التطوير وإنشاء مشروع Django
تأكد من تثبيت Python و pip على جهازك. ثم قم بتثبيت Django:
pip install django
--
* أنشئ مشروع Django جديدًا باسم quiz_platform:
django-admin startproject quiz_platform
cd quiz_platform
--
* أنشئ تطبيقًا داخل المشروع باسم quiz :
python manage.py startapp quiz
--
الخطوة 2: تعريف نماذج البيانات (Models)
في ملف quiz/models.py، سنقوم بتعريف نماذج البيانات الأساسية
للاختبارات والأسئلة والاختيارات وإجابات المستخدم :
Python
from django.db import modelsfrom django.contrib.auth.models import User
class Quiz(models.Model): title = models.CharField(max_length=255) description = models.TextField(blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True)
def __str__(self): return self.title
class Question(models.Model): quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name='questions') text = models.TextField() order = models.IntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True)
class Meta: ordering = ['order']
def __str__(self): return self.text[:50] + "..."
class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='choices') text = models.CharField(max_length=255) is_correct = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True)
def __str__(self): return self.text
class UserAnswer(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE) question = models.ForeignKey(Question, on_delete=models.CASCADE) choice = models.ForeignKey(Choice, on_delete=models.CASCADE) submitted_at = models.DateTimeField(auto_now_add=True)
class Meta: unique_together = ('user', 'quiz', 'question')
def __str__(self): return f"{self.user.username} - {self.question.text[:20]} - {self.choice.text[:20]}"
--
* أضف تطبيق quiz إلى قائمة INSTALLED_APPS في ملف
quiz_platform/settings.py :
Python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'quiz', # إضافة تطبيق quiz هنا
]
--
* قم بإنشاء التغييرات وتنفيذها :
python manage.py makemigrations quiz
python manage.py migrate
--
الخطوة 3: إنشاء واجهة المستخدم (Templates)
أنشئ مجلدًا باسم templates داخل مجلد تطبيق quiz. ثم أنشئ ملفات HTML التالية:
* quiz/templates/quiz/quiz_list.html:
لعرض قائمة الاختبارات المتاحة:
HTML
<!DOCTYPE html>
<html>
<head>
<title>قائمة الاختبارات</title>
</head>
<body>
<h1>الاختبارات المتاحة</h1>
<ul>
{% for quiz in quizzes %}
<li><a href="{% url 'take_quiz' quiz.id %}">{{ quiz.title }}</a></li>
{% empty %}
<li>لا توجد اختبارات متاحة حاليًا.</li>
{% endfor %}
</ul>
</body>
</html>
--
* quiz/templates/quiz/take_quiz.html:
لعرض أسئلة الاختبار ونموذج الإجابة:
HTML
<!DOCTYPE html><html><head> <title>{{ quiz.title }}</title></head><body> <h1>{{ quiz.title }}</h1> <form method="post"> {% csrf_token %} {% for question in questions %} <div> <h3>{{ forloop.counter }}. {{ question.text }}</h3> <ul> {% for choice in question.choices.all %} <li> <input type="radio" name="question_{{ question.id }}" value="{{ choice.id }}" required> <label for="choice_{{ choice.id }}">{{ choice.text }}</label> </li> {% endfor %} </ul> </div> {% endfor %} <button type="submit">إرسال الإجابات</button> </form> <a href="{% url 'quiz_list' %}">العودة إلى قائمة الاختبارات</a></body></html>
--
* quiz/templates/quiz/quiz_results.html :
لعرض نتائج الاختبار:
HTML
<!DOCTYPE html>
<html>
<head>
<title>نتائج الاختبار</title>
</head>
<body>
<h1>نتائج اختبار {{ quiz.title }}</h1>
<p>إجمالي عدد الأسئلة: {{ total_questions }}</p>
<p>عدد الإجابات الصحيحة: {{ correct_answers }}</p>
<p>النتيجة: {{ score }}%</p>
<a href="{% url 'quiz_list' %}">العودة إلى قائمة الاختبارات</a>
</body>
</html>
--
الخطوة 4: إنشاء النماذج (Forms)
في ملف quiz/forms.py (إذا لم يكن موجودًا، قم بإنشائه)، قد تحتاج إلى
نموذج مخصص للتحقق من صحة الإجابات إذا كنت تنفذ منطقًا أكثر تعقيدًا.
في هذا المثال البسيط، سنعتمد على معالجة POST مباشرة في طريقة العرض.
الخطوة 5: إنشاء طرق العرض (Views)
في ملف quiz/views.py، سنقوم بإنشاء طرق العرض التي
تتحكم في منطق التطبيق وتعرض القوالب:
Python
from django.shortcuts import render, get_object_or_404, redirectfrom .models import Quiz, Question, Choice, UserAnswerfrom django.contrib.auth.decorators import login_requiredfrom django.db import transaction
def quiz_list(request): quizzes = Quiz.objects.all() return render(request, 'quiz/quiz_list.html', {'quizzes': quizzes})
@login_requireddef take_quiz(request, quiz_id): quiz = get_object_or_404(Quiz, pk=quiz_id) questions = quiz.questions.all() if request.method == 'POST': score = 0 total_questions = questions.count() with transaction.atomic(): for question in questions: choice_id = request.POST.get(f'question_{question.id}') if choice_id: try: choice = Choice.objects.get(pk=choice_id, question=question) UserAnswer.objects.create(user=request.user, quiz=quiz, question=question, choice=choice) if choice.is_correct: score += 1 except Choice.DoesNotExist: pass percentage = (score / total_questions) * 100 if total_questions > 0 else 0 return render(request, 'quiz/quiz_results.html', {'quiz': quiz, 'total_questions': total_questions, 'correct_answers': score, 'score': percentage}) else: return render(request, 'quiz/take_quiz.html', {'quiz': quiz, 'questions': questions})
--
الخطوة 6: تعريف مسارات URL (URLs)
في ملف quiz/urls.py (إذا لم يكن موجودًا، قم بإنشائه) :
Python
from django.urls import path
from . import views
urlpatterns = [
path('', views.quiz_list, name='quiz_list'),
path('<int:quiz_id>/take/', views.take_quiz, name='take_quiz'),
]
--
* قم بتضمين مسارات تطبيق quiz في ملف quiz_platform/urls.py:
Python
from django.contrib import admin
from django.urls import path, include
from django.shortcuts import redirect
urlpatterns = [
path('admin/', admin.site.urls),
path('quizzes/', include('quiz.urls')),
path('accounts/', include('django.contrib.auth.urls')), # لتسجيل الدخول والخروج
path('', lambda request: redirect('/quizzes/')), # إعادة التوجيه إلى قائمة الاختبارات عند الوصول إلى الجذر
]
--
الخطوة 7: إنشاء واجهة إدارة (Django Admin)
لتسهيل إدارة الاختبارات والأسئلة والاختيارات، قم بتسجيل النماذج في
Django Admin في ملف quiz/admin.py :
Python
from django.contrib import adminfrom .models import Quiz, Question, Choice, UserAnswer
class ChoiceInline(admin.TabularInline): model = Choice extra = 3
@admin.register(Quiz)class QuizAdmin(admin.ModelAdmin): list_display = ('title', 'created_at')
@admin.register(Question)class QuestionAdmin(admin.ModelAdmin): list_display = ('text', 'quiz', 'order') list_filter = ('quiz',) inlines = [ChoiceInline] search_fields = ('text',)
@admin.register(Choice)class ChoiceAdmin(admin.ModelAdmin): list_display = ('text', 'question', 'is_correct') list_filter = ('question',)
@admin.register(UserAnswer)class UserAnswerAdmin(admin.ModelAdmin): list_display = ('user', 'quiz', 'question', 'choice', 'submitted_at') list_filter = ('quiz', 'user')
--
* قم بإنشاء مستخدم مسؤول إذا لم يكن لديك واحدًا بالفعل :
python manage.py createsuperuser
--
* ثم قم بتشغيل خادم التطوير وقم بزيارة http://127.0.0.1:8000/admin/
لتسجيل الدخول وإدارة الاختبارات والأسئلة والاختيارات.
الخطوة 8: حفظ النقاط (بيانات الإجابات)
يتم حفظ بيانات إجابات المستخدم في قاعدة البيانات عند تقديم النموذج
في طريقة العرض take_quiz. يتم إنشاء كائن UserAnswer لكل
سؤال يجيب عليه المستخدم، ويرتبط بالمستخدم والاختبار والسؤال والاجابة التي اختارها.
Django ORM يتولى عملية التفاعل مع قاعدة البيانات وحفظ
البيانات بناءً على تعريف النماذج والعلاقات بينها.
الخطوة 9: نشر التطبيق
لنشر تطبيق Django، يمكنك اتباع الخطوات العامة التالية (باستخدام Gunicorn و Nginx كمثال):
* تثبيت Gunicorn :
pip install gunicorn
--
* اختبار Gunicorn: انتقل إلى مجلد مشروع Django وقم بتشغيل:
gunicorn quiz_platform.wsgi:application
--
* تثبيت Nginx :
sudo apt update
sudo apt install nginx
--
* تكوين Nginx : قم بإنشاء ملف تكوين جديد للموقع الخاص بك في
/etc/nginx/sites-available/ (مثل quiz_platform) وقم بربطه
بـ /etc/nginx/sites-enabled/. مثال على التكوين:
Nginx
server { listen 80; server_name your_domain_or_IP;
location /static/ { alias /path/to/your/project/staticfiles/; }
location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }}
--
* استبدل your_domain_or_IP بعنوان نطاقك أو
عنوان IP الخاص بالخادم، و /path/to/your/project/staticfiles/ بالمسار
الفعلي لمجلد الملفات الثابتة الخاص بك.
* جمع الملفات الثابتة: قبل النشر، قم بجمع الملفات الثابتة باستخدام :
python manage.py collectstatic
--
* تكوين نظام إدارة العمليات (مثل systemd) لتشغيل Gunicorn تلقائيًا.
* إعادة تشغيل Nginx :
sudo systemctl restart nginx
--
* تأمين الخادم الخاص بك (مثل إعداد جدار حماية وتكوين
HTTPS باستخدام Let's Encrypt).
* الخلاصة :
لقد استعرضنا الخطوات الأساسية لبرمجة منصة مسابقات أو اختبارات تفاعلية
بسيطة باستخدام Python Django، بدءًا من إنشاء واجهة المستخدم لعرض
الاختبارات والأسئلة، مرورًا بتعريف نماذج البيانات لتمثيل الاختبارات والأسئلة
والاختيارات، وصولًا إلى تمكين المستخدمين من تقديم الإجابات و حفظ هذه البيانات
في قاعدة البيانات وحساب النتائج، وتقديم نظرة عامة على عملية نشر التطبيق.
يمكنك الآن تطوير هذه المنصة بإضافة المزيد من الميزات مثل أنواع مختلفة
من الأسئلة، وتوقيت الاختبارات، وعرض تفاصيل الإجابات الصحيحة والخاطئة،
وإدارة نتائج المستخدمين بشكل متقدم، والمزيد.
تذكر دائمًا التركيز على أمان التطبيق وحماية بيانات المستخدمين.