نظام تسجيل النشاطات (Activity Logs) داخل لوحة التحكم
(من دخل؟ ماذا فعل؟ متى؟ ولمَن؟)
الهدف: تتبّع كل العمليات الحسّاسة داخل النظام (دخول، إضافة مستخدم، تعديل، حذف…).
🎯 ماذا سنبني؟
جدول لتخزين السجلات (Logs)تسجيل تلقائي عند:
- تسجيل الدخول
- إضافة مستخدم
- تعديل مستخدم
- حذف مستخدم
واجهة جميلة باستخدام Bootstrap
🧱 1️⃣ إنشاء موديل ActivityLog
dashboard/models.py
from django.db import models
from django.contrib.auth.models import User
class ActivityLog(models.Model):
ACTION_CHOICES = (
("login", "Login"),
("create_user", "Create User"),
("edit_user", "Edit User"),
("delete_user", "Delete User"),
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
action = models.CharField(max_length=50, choices=ACTION_CHOICES)
target = models.CharField(max_length=255, blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username} - {self.action} - {self.timestamp}"
ثم نفّذ:
python manage.py makemigrations
python manage.py migrate
🧠 2️⃣ دالة مساعدة لتسجيل النشاط
dashboard/utils.py
from .models import ActivityLog
def log_activity(user, action, target=None):
ActivityLog.objects.create(user=user, action=action, target=target)
🧠 3️⃣ ربط التسجيل بالأحداث (Views)
أمثلة داخل views.py
عند تسجيل الدخول:
from .utils import log_activity
# بعد login(request, user)
log_activity(user, "login")
عند إضافة مستخدم:
log_activity(request.user, "create_user", target=user.username)
عند تعديل مستخدم:
log_activity(request.user, "edit_user", target=user.username)
عند حذف مستخدم:
log_activity(request.user, "delete_user", target=user.username)
🌐 4️⃣ View عرض السجلات (Admin فقط)
dashboard/views.py
from .models import ActivityLog
@login_required
@admin_required
def activity_logs(request):
logs = ActivityLog.objects.select_related("user").order_by("-timestamp")[:200]
return render(request, "dashboard/logs.html", {"logs": logs})
🌐 5️⃣ URL صفحة السجلات
dashboard/urls.py
path("logs/", activity_logs, name="activity_logs"),
🎨 6️⃣ واجهة عرض السجلات
dashboard/templates/dashboard/logs.html
{% extends "dashboard/base.html" %}
{% block content %}
<h3>سجل النشاطات</h3>
<table class="table table-striped mt-4">
<thead class="table-dark">
<tr>
<th>المستخدم</th>
<th>العملية</th>
<th>الهدف</th>
<th>التاريخ</th>
</tr>
</thead>
<tbody>
{% for log in logs %}
<tr>
<td>{{ log.user.username }}</td>
<td>{{ log.get_action_display }}</td>
<td>{{ log.target }}</td>
<td>{{ log.timestamp|date:"Y-m-d H:i" }}</td>
</tr>
{% empty %}
<tr>
<td colspan="4">لا توجد سجلات بعد</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
🧪 تمرين الدرس الثامن
نفّذ التالي:
- أضف فلترة السجلات حسب المستخدم
- أضف فلترة حسب نوع العملية
- إضافة زر تصدير CSV لسجل النشاط
✅ حل تمرين الدرس الثامن – Activity Logs (فلترة + تصدير CSV)
✔ المطلوب:
- فلترة السجلات حسب المستخدم
- فلترة حسب نوع العملية (Action)
- تصدير السجلات إلى ملف CSV
🧱 1️⃣ تحديث View السجلات لإضافة الفلترة
dashboard/views.py
import csv
from django.http import HttpResponse
from .models import ActivityLog
@login_required
@admin_required
def activity_logs(request):
logs = ActivityLog.objects.select_related("user").order_by("-timestamp")
user_id = request.GET.get("user")
action = request.GET.get("action")
if user_id:
logs = logs.filter(user_id=user_id)
if action:
logs = logs.filter(action=action)
# 🧾 تصدير CSV
if request.GET.get("export") == "csv":
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="activity_logs.csv"'
writer = csv.writer(response)
writer.writerow(["User", "Action", "Target", "Timestamp"])
for log in logs:
writer.writerow([
log.user.username,
log.get_action_display(),
log.target,
log.timestamp.strftime("%Y-%m-%d %H:%M"),
])
return response
return render(request, "dashboard/logs.html", {
"logs": logs,
})
🧱 2️⃣ تحديث واجهة عرض السجلات (إضافة فلترة)
dashboard/templates/dashboard/logs.html
{% extends "dashboard/base.html" %}
{% block content %}
<h3>سجل النشاطات</h3>
<form method="get" class="row g-2 mb-3">
<div class="col-md-4">
<select name="user" class="form-select">
<option value="">كل المستخدمين</option>
{% for u in logs|dictsort:"user.id" %}
<option value="{{ u.user.id }}">{{ u.user.username }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-4">
<select name="action" class="form-select">
<option value="">كل العمليات</option>
<option value="login">Login</option>
<option value="create_user">Create User</option>
<option value="edit_user">Edit User</option>
<option value="delete_user">Delete User</option>
</select>
</div>
<div class="col-md-4 d-flex gap-2">
<button class="btn btn-primary">تصفية</button>
<a href="?export=csv" class="btn btn-success">تصدير CSV</a>
</div>
</form>
<table class="table table-striped">
<thead class="table-dark">
<tr>
<th>المستخدم</th>
<th>العملية</th>
<th>الهدف</th>
<th>التاريخ</th>
</tr>
</thead>
<tbody>
{% for log in logs %}
<tr>
<td>{{ log.user.username }}</td>
<td>{{ log.get_action_display }}</td>
<td>{{ log.target }}</td>
<td>{{ log.timestamp|date:"Y-m-d H:i" }}</td>
</tr>
{% empty %}
<tr>
<td colspan="4">لا توجد سجلات</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
💡 ملاحظة احترافية:
إذا أردت قائمة مستخدمين أدق في الفلترة، يمكننا تمريرusers = User.objects.all()من الـ View بدل الاعتماد على logs فقط.
🧪 ماذا تحقق الآن؟
✔ فلترة ديناميكية حسب المستخدم
✔ فلترة حسب نوع العملية
✔ تصدير CSV بضغطة زر
✔ نظام Logs احترافي شبيه بالأنظمة التجارية
✔ مناسب للأرشفة والمراجعة الإدارية
🏁 الخلاصة
بهذا الحل:
- أصبح لديك نظام مراقبة كامل
- المشروع أصبح أقرب لتطبيقات SaaS حقيقية
- جاهز لإضافة تقارير ورسوم بيانية لاحقًا

