
كيفية انشاء موقع أسئلة وأجوبة باستخدام Python Django
في هذا الدليل الشامل سنستعرض خطوات بناء موقع بسيط للأسئلة والأجوبة
(يشبه Stack Overflow) باستخدام لغة البرمجة Python وإطار العمل Django.
سنغطي كل شيء بدءًا من تصميم وإنشاء واجهة المستخدم لعرض الأسئلة وطرحها
والإجابة عليها، مرورًا بتعريف نماذج البيانات لتخزين معلومات الأسئلة والأجوبة والمستخدمين،
وصولًا إلى حفظ هذه البيانات ونشر التطبيق.
خطوات برمجة موقع أسئلة وأجوبة (مثل Stack Overflow)
انضم إلينا في رحلة بناء عبر الإنترنت من خلال
إنشاء موقع أسئلة وأجوبة قوي وفعال باستخدام Python Django!
في هذا الدليل الشامل، سنستكشف الخطوات العملية لإنشاء منصة تفاعلية تشبه
Stack Overflow، حيث يمكن للمستخدمين طرح الأسئلة وتلقي الإجابات وتبادل المعرفة.
سواء كنت مطورًا طموحًا يسعى لتوسيع مهاراته أو صاحب رؤية يرغب في إنشاء
مجتمع متخصص، سيزودك هذا المقال بالأساس المتين والأكواد اللازمة لتحويل
هذه الفكرة إلى واقع رقمي حيوي. سنغطي كل جانب من جوانب التطوير، بدءًا من تصميم
واجهة المستخدم البديهية وصولًا إلى نشر التطبيق ليصبح متاحًا للجميع.
استعد لتعلم كيفية تسخير قوة Django لإنشاء منصة أسئلة وأجوبة ديناميكية وقابلة للتوسع :
الخطوة 1: إعداد بيئة التطوير وإنشاء مشروع Django
تأكد من تثبيت Python و pip على جهازك. ثم قم بتثبيت Django:
pip install django
--
* أنشئ مشروع Django جديدًا باسم qa_site:
django-admin startproject qa_site
cd qa_site
--
* أنشئ تطبيقًا داخل المشروع باسم qanda:
python manage.py startapp qanda
--
الخطوة 2: تعريف نماذج البيانات (Models)
في ملف qanda/models.py، سنقوم بتعريف نماذج البيانات
الأساسية للأسئلة والأجوبة والمستخدمين:
Python
from django.db import modelsfrom django.contrib.auth.models import Userfrom django.utils import timezone
class Question(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) title = models.CharField(max_length=255) slug = models.SlugField(unique=True) body = models.TextField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
def __str__(self): return self.title
class Meta: ordering = ['-created_at']
class Answer(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) question = models.ForeignKey(Question, related_name='answers', on_delete=models.CASCADE) body = models.TextField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) is_best_answer = models.BooleanField(default=False)
class Meta: ordering = ['created_at']
def __str__(self): return f"Answer by {self.user.username} to {self.question.title[:50]}..."
* أضف تطبيق qanda إلى قائمة INSTALLED_APPS في
ملف qa_site/settings.py :
Python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'qanda', # إضافة تطبيق qanda هنا
]
--
* قم بإنشاء التغييرات وتنفيذها :
python manage.py makemigrations qanda
python manage.py migrate
--
الخطوة 3: إنشاء واجهة المستخدم (Templates)
أنشئ مجلدًا باسم templates داخل مجلد تطبيق qanda.
ثم أنشئ ملفات HTML التالية :
* qanda/templates/qanda/question_list.html:
لعرض قائمة الأسئلة :
HTML
<!DOCTYPE html><html><head> <title>موقع الأسئلة والأجوبة</title></head><body> <h1>آخر الأسئلة</h1> <ul> {% for question in questions %} <li> <h2><a href="{% url 'question_detail' question.slug %}">{{ question.title }}</a></h2> <p>طرح بواسطة: {{ question.user.username }} | تاريخ الطرح: {{ question.created_at }} | الإجابات: {{ question.answers.count }}</p> </li> {% empty %} <li>لا توجد أسئلة مطروحة حتى الآن.</li> {% endfor %} </ul> <p><a href="{% url 'ask_question' %}">طرح سؤال جديد</a></p></body></html>
* qanda/templates/qanda/question_detail.html:
لعرض تفاصيل السؤال والإجابات :
HTML
<!DOCTYPE html><html><head> <title>{{ question.title }} - موقع الأسئلة والأجوبة</title></head><body> <h1>{{ question.title }}</h1> <p>طرح بواسطة: {{ question.user.username }} | تاريخ الطرح: {{ question.created_at }}</p> <div class="question-body"> {{ question.body|linebreaksbr }} </div>
<h2>الإجابات</h2> {% if question.answers.all %} <ul> {% for answer in question.answers.all %} <li> <p>بواسطة: {{ answer.user.username }} | تاريخ الإجابة: {{ answer.created_at }}</p> <div class="answer-body"> {{ answer.body|linebreaksbr }} </div> {% if request.user.is_authenticated and request.user == question.user and not question.answer_set.filter(is_best_answer=True).exists %} <form method="post" action="{% url 'mark_best_answer' answer.id %}"> {% csrf_token %} <button type="submit">تحديد كأفضل إجابة</button> </form> {% endif %} {% if answer.is_best_answer %} <p><b>(أفضل إجابة)</b></p> {% endif %} </li> {% endfor %} </ul> {% else %} <p>لا توجد إجابات لهذا السؤال حتى الآن.</p> {% endif %}
{% if request.user.is_authenticated %} <h2>أجب على هذا السؤال</h2> <form method="post" action="{% url 'answer_question' question.id %}"> {% csrf_token %} {{ answer_form.as_p }} <button type="submit">نشر الإجابة</button> </form> {% else %} <p><a href="{% url 'login' %}">سجل الدخول</a> للإجابة على هذا السؤال.</p> {% endif %}
<p><a href="{% url 'question_list' %}">العودة إلى قائمة الأسئلة</a></p></body></html>
* qanda/templates/qanda/ask_question.html:
لنموذج طرح سؤال جديد :
HTML
<!DOCTYPE html>
<html>
<head>
<title>طرح سؤال جديد</title>
</head>
<body>
<h1>طرح سؤال جديد</h1>
<form method="post">
{% csrf_token %}
{{ question_form.as_p }}
<button type="submit">نشر السؤال</button>
</form>
<p><a href="{% url 'question_list' %}">العودة إلى قائمة الأسئلة</a></p>
</body>
</html>
--
الخطوة 4: إنشاء النماذج (Forms)
في ملف qanda/forms.py (إذا لم يكن موجودًا، قم بإنشائه):
Python
from django import forms
from .models import Question, Answer
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['title', 'body']
class AnswerForm(forms.ModelForm):
class Meta:
model = Answer
fields = ['body']
widgets = {
'body': forms.Textarea(attrs={'rows': 5})
}
--
الخطوة 5: إنشاء طرق العرض (Views)
في ملف qanda/views.py، سنقوم بإنشاء طرق العرض التي تتحكم في
منطق التطبيق وتعرض القوالب :
Python
from django.shortcuts import render, redirect, get_object_or_404from django.contrib.auth.decorators import login_requiredfrom django.utils.text import slugifyfrom .models import Question, Answerfrom .forms import QuestionForm, AnswerForm
def question_list(request): questions = Question.objects.all() context = {'questions': questions} return render(request, 'qanda/question_list.html', context)
def question_detail(request, slug): question = get_object_or_404(Question, slug=slug) answer_form = AnswerForm() context = {'question': question, 'answer_form': answer_form} return render(request, 'qanda/question_detail.html', context)
@login_requireddef ask_question(request): if request.method == 'POST': form = QuestionForm(request.POST) if form.is_valid(): question = form.save(commit=False) question.user = request.user question.slug = slugify(question.title) question.save() return redirect('question_detail', slug=question.slug) else: form = QuestionForm() context = {'question_form': form} return render(request, 'qanda/ask_question.html', context)
@login_requireddef answer_question(request, question_id): question = get_object_or_404(Question, id=question_id) if request.method == 'POST': form = AnswerForm(request.POST) if form.is_valid(): answer = form.save(commit=False) answer.user = request.user answer.question = question answer.save() return redirect('question_detail', slug=question.slug) else: form = AnswerForm() # لا نعرض النموذج هنا، يتم عرضه في صفحة تفاصيل السؤال return redirect('question_detail', slug=question.slug)
@login_requireddef mark_best_answer(request, answer_id): answer = get_object_or_404(Answer, id=answer_id, question__user=request.user) question = answer.question question.answer_set.update(is_best_answer=False) # إزالة العلامة من أي إجابة أخرى answer.is_best_answer = True answer.save() return redirect('question_detail', slug=question.slug)
* ملاحظة : تتطلب هذه الطرق تسجيل دخول المستخدم. تأكد من إعداد نظام
مصادقة المستخدم في Django (يمكن استخدام تطبيق django.contrib.auth).
الخطوة 6: تعريف مسارات URL (URLs)
في ملف qanda/urls.py (إذا لم يكن موجودًا، قم بإنشائه) :
Python
from django.urls import path
from . import views
urlpatterns = [
path('', views.question_list, name='question_list'),
path('ask/', views.ask_question, name='ask_question'),
path('<slug:slug>/', views.question_detail, name='question_detail'),
path('<int:question_id>/answer/', views.answer_question, name='answer_question'),
path('answer/<int:answer_id>/best/', views.mark_best_answer, name='mark_best_answer'),
]
--
* قم بتضمين مسارات تطبيق qanda في ملف qa_site/urls.py :
Python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')), # لتسجيل الدخول والخروج
path('', include('qanda.urls')), # تضمين مسارات تطبيق qanda
]
--
الخطوة 7: تفعيل مصادقة المستخدم
إذا لم تقم بذلك بالفعل، قم بتفعيل تطبيق django.contrib.auth
وتكوين مسارات تسجيل الدخول والخروج في ملف qa_site/urls.py كما
هو موضح أعلاه. يمكنك أيضًا إنشاء قوالب تسجيل الدخول (login.html) و
تسجيل المستخدم (registration/register.html) إذا كنت ترغب في توفير تسجيل مستخدم جديد.
الخطوة 8: حفظ النقاط (بيانات الأسئلة والأجوبة)
لقد قمنا بالفعل بحفظ بيانات الأسئلة والأجوبة في قاعدة البيانات في
طرق العرض ask_question و answer_question و mark_best_answer في
ملف qanda/views.py. يتم إنشاء سجلات جديدة في نماذج
Question و Answer لتخزين معلومات الأسئلة والأجوبة.
الخطوة 9: نشر التطبيق
لنشر تطبيق Django، يمكنك اتباع نفس الخطوات العامة المذكورة في
قسم النشر في مثال المتجر الإلكتروني البسيط (باستخدام Gunicorn و Nginx أو
أي خادم ويب و WSGI آخر تفضله). تأكد من تكوين خادم الويب الخاص بك
لخدمة الملفات الثابتة التي تم جمعها بواسطة python manage.py collectstatic.
* الخلاصة
لقد قمنا خلال الخطوات الأساسية لبناء موقع بسيط للأسئلة والأجوبة
(مثل Stack Overflow) باستخدام Python Django. بدءًا من إعداد المشروع
وتعريف نماذج البيانات، مرورًا بإنشاء واجهة المستخدم والنماذج وطرق
العرض والمسارات، وصولًا إلى حفظ بيانات الأسئلة والأجوبة ونشر التطبيق.
يمكنك الآن توسيع هذا الموقع بإضافة المزيد من الميزات مثل التصويت،
والتعليقات على الإجابات، والبحث، وأنظمة الوسوم (Tags)، ولوحة إدارة متقدمة.
Django يوفر لك إطار عمل قويًا لبناء منصات تفاعلية للمجتمع عبر الإنترنت.