🎯 الهدف من الدرس:
في هذا الدرس سنتعلم كيف نُظهر للمستخدم رسائل فورية مؤقتة (Flash Messages) بعد تنفيذ عمليات مثل:
- ✅ إضافة ملاحظة جديدة
- ✏️ تعديل ملاحظة
- 🗑️ حذف ملاحظة
تساعد هذه التنبيهات في تحسين تجربة المستخدم عبر عرض إشعارات أنيقة في واجهة الموقع.
🧩 أولاً: ما هي Flash Messages في Flask؟
هي طريقة بسيطة لعرض رسالة لمرة واحدة فقط بعد تنفيذ إجراء معيّن (مثل نجاح أو خطأ)،
ويتم تخزينها مؤقتًا في Session ثم تُزال بعد عرضها.
🧱 ثانياً: إعداد الكود في Flask
افتح ملف app.py
وأضف السطر التالي بعد إنشاء التطبيق:
from flask import Flask, render_template, request, redirect, url_for, flash, session
ثم أضف مفتاح سرّي لتفعيل الـ session:
app = Flask(__name__)
app.secret_key = "my_secret_key_123" # مفتاح تشفير ضروري للـ flash messages
🧩 ثالثاً: تعديل المسارات لإرسال الرسائل
سنضيف رسالة بعد كل عملية رئيسية (إضافة – تعديل – حذف).
🔹 عند إضافة ملاحظة:
@app.route('/add', methods=['POST'])
def add_note():
title = request.form['title']
content = request.form['content']
if not title or not content:
flash("⚠️ الرجاء إدخال عنوان ومحتوى الملاحظة.", "warning")
return redirect(url_for('index'))
conn = get_db_connection()
conn.execute('INSERT INTO notes (title, content, updated_at) VALUES (?, ?, datetime("now"))',
(title, content))
conn.commit()
conn.close()
flash("✅ تمت إضافة الملاحظة بنجاح!", "success")
return redirect(url_for('index'))
🔹 عند تعديل ملاحظة:
@app.route('/edit/<int:id>', methods=['GET', 'POST'])
def edit_note(id):
conn = get_db_connection()
note = conn.execute('SELECT * FROM notes WHERE id = ?', (id,)).fetchone()
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
conn.execute('UPDATE notes SET title = ?, content = ?, updated_at = datetime("now") WHERE id = ?',
(title, content, id))
conn.commit()
conn.close()
flash("✏️ تم تعديل الملاحظة بنجاح!", "info")
return redirect(url_for('index'))
conn.close()
return render_template('edit.html', note=note)
🔹 عند حذف ملاحظة:
@app.route('/delete/<int:id>')
def delete_note(id):
conn = get_db_connection()
conn.execute('DELETE FROM notes WHERE id = ?', (id,))
conn.commit()
conn.close()
flash("🗑️ تم حذف الملاحظة بنجاح!", "danger")
return redirect(url_for('index'))
🧩 رابعاً: تعديل صفحة العرض index.html
سنضيف مقطع كود لعرض الرسائل أعلى الصفحة (تحت شريط العنوان مثلاً):
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="container mt-3">
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
🧩 خامساً: تحسين المظهر باستخدام Bootstrap
يُفضل إضافة Bootstrap في رأس الصفحة إن لم يكن مضافًا مسبقًا:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
الـ alert
في Bootstrap يدعم الألوان التالية:
alert-success
✅ نجاحalert-info
💡 ملاحظةalert-warning
⚠️ تحذيرalert-danger
❌ خطأ أو حذف
🎮 تجربة عملية
- أضف ملاحظة جديدة → ستظهر رسالة نجاح خضراء.
- عدّل الملاحظة → ستظهر رسالة تعديل زرقاء.
- احذف الملاحظة → ستظهر رسالة حمراء.
🧠 خلاصة الدرس
- Flash Messages تجعل واجهة المستخدم أكثر تفاعلاً.
- يتم تمرير الرسائل عبر
flash()
وعرضها بـget_flashed_messages()
. - يمكن تخصيص الألوان والرموز لتمييز نوع الرسالة.
💪 تمرين الدرس الخامس:
🎯 المطلوب:
أضف في تطبيقك تنبيه خاص عند محاولة إضافة ملاحظة بعنوان مكرر (نفس الاسم موجود مسبقًا)،
يظهر برسالة:
⚠️ "هذا العنوان مستخدم من قبل، يرجى اختيار عنوان آخر."
📘 تلميح:
استخدم استعلام SQL للتحقق:
note_exists = conn.execute('SELECT * FROM notes WHERE title = ?', (title,)).fetchone()
حل تمرين الدرس الخامس:
🎯 "إضافة تنبيهات وإشعارات فورية (Flash Messages)"🧠 الفكرة العامة:
نضيف تنبيهات للمستخدم بعد كل عملية (إضافة، تعديل، حذف) باستخدام flash()
من مكتبة Flask، ونظهرها في الواجهة باستخدام Bootstrap.
📁 1. تعديل الملف app.py
from flask import Flask, render_template, request, redirect, url_for, flash
import sqlite3
app = Flask(__name__)
app.secret_key = 'supersecretkey' # ضروري لاستخدام flash
def get_db_connection():
conn = sqlite3.connect('notes.db')
conn.row_factory = sqlite3.Row
return conn
@app.route('/')
def index():
conn = get_db_connection()
notes = conn.execute('SELECT * FROM notes').fetchall()
conn.close()
return render_template('index.html', notes=notes)
@app.route('/add', methods=['POST'])
def add_note():
title = request.form['title']
content = request.form['content']
if not title or not content:
flash('⚠️ العنوان والمحتوى مطلوبان!', 'warning')
return redirect(url_for('index'))
conn = get_db_connection()
conn.execute('INSERT INTO notes (title, content) VALUES (?, ?)', (title, content))
conn.commit()
conn.close()
flash('✅ تم إضافة الملاحظة بنجاح!', 'success')
return redirect(url_for('index'))
@app.route('/delete/<int:id>')
def delete_note(id):
conn = get_db_connection()
conn.execute('DELETE FROM notes WHERE id = ?', (id,))
conn.commit()
conn.close()
flash('🗑️ تم حذف الملاحظة بنجاح!', 'info')
return redirect(url_for('index'))
if __name__ == '__main__':
app.run(debug=True)
📄 2. تعديل ملف templates/index.html
أضف قسم عرض التنبيهات أعلى الصفحة:
<!DOCTYPE html>
<html lang="ar">
<head>
<meta charset="UTF-8">
<title>تطبيق الملاحظات</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
</head>
<body class="bg-light">
<div class="container mt-4">
<!-- عرض التنبيهات -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<h2 class="text-center mb-4">📝 تطبيق الملاحظات</h2>
<form method="POST" action="/add" class="mb-3">
<input type="text" name="title" class="form-control mb-2" placeholder="العنوان">
<textarea name="content" class="form-control mb-2" placeholder="المحتوى"></textarea>
<button type="submit" class="btn btn-success w-100">إضافة ملاحظة</button>
</form>
<ul class="list-group">
{% for note in notes %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<div>
<strong>{{ note['title'] }}</strong><br>
<small>{{ note['content'] }}</small>
</div>
<a href="/delete/{{ note['id'] }}" class="btn btn-danger btn-sm">حذف</a>
</li>
{% endfor %}
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
✨ النتيجة النهائية:
- عند إضافة ملاحظة جديدة → يظهر تنبيه أخضر ✅
- عند حذف ملاحظة → يظهر تنبيه أزرق 🗑️
- عند ترك الحقول فارغة → يظهر تنبيه أصفر ⚠️