دليل شامل لبناء تطبيق CRUD باستخدام Flask و SQLite: خطوات عملية للمبتدئين
المقدمة
إطار Flask هو أحد أشهر أطر العمل الخفيفة في بايثون لتطوير تطبيقات الويب. يتميز Flask بالمرونة وسهولة الاستخدام، مما يجعله خياراً ممتازاً للمشاريع الصغيرة والمتوسطة. في هذا الدليل، سنقوم ببناء تطبيق بسيط يدعم عمليات CRUD (إنشاء، قراءة، تحديث، حذف) باستخدام Flask وقاعدة بيانات SQLite. تعتبر عمليات CRUD أساس أي تطبيق ويب تفاعلي، لذا فإن فهم كيفية تنفيذها يعد خطوة أساسية لكل مطور.
المتطلبات الأساسية
- معرفة أساسية بلغة بايثون
- فهم أساسيات HTML و CSS
- تثبيت Flask و SQLite
- تثبيت أداة إدارة الحزم
pip
الخطوة الأولى: إعداد البيئة
أولاً، سنقوم بإعداد بيئة التطوير وتثبيت Flask. يُفضل استخدام بيئة افتراضية لعزل حزم المشروع.
إنشاء بيئة افتراضية
لإنشاء بيئة افتراضية، استخدم الأوامر التالية في الطرفية:
python -m venv venv
source venv/bin/activate # على نظام Windows استخدم: venv\Scripts\activate
تثبيت Flask و SQLite
بعد تنشيط البيئة الافتراضية، قم بتثبيت Flask باستخدام pip
:
pip install Flask
pip install flask_sqlite3
تأكد من تثبيت SQLite، والذي غالباً ما يكون مثبتاً مسبقاً على معظم أنظمة التشغيل.
الخطوة الثانية: إنشاء التطبيق الأساسي
نبدأ بإنشاء ملف app.py
يحتوي على التطبيق الأساسي لـ Flask.
from flask import Flask, render_template, request, redirect, url_for
app = Flask(__name__)
@app.route('/')
def index():
return "مرحباً بك في تطبيق CRUD باستخدام Flask!"
if __name__ == '__main__':
app.run(debug=True)
هذا الكود البسيط يقوم بإنشاء تطبيق Flask مع صفحة رئيسية ترحب بالمستخدم. يمكنك تشغيل التطبيق باستخدام الأمر python app.py
والانتقال إلى http://127.0.0.1:5000/
في متصفحك لرؤية النتيجة.
الخطوة الثالثة: إعداد قاعدة البيانات
سنقوم الآن بإعداد قاعدة بيانات SQLite لتخزين البيانات. سنقوم بإنشاء جدول يسمى entries
يحتوي على حقول id
، title
، و content
.
import sqlite3
def init_sqlite_db():
conn = sqlite3.connect('database.db')
print("تم الاتصال بقاعدة البيانات بنجاح")
conn.execute('''
CREATE TABLE IF NOT EXISTS entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT NOT NULL
)
''')
print("تم إنشاء الجدول بنجاح")
conn.close()
init_sqlite_db()
قم بتشغيل هذا الكود مرة واحدة لإنشاء قاعدة البيانات والجدول المطلوب.
الخطوة الرابعة: إنشاء العمليات (CRUD)
سنقوم الآن بإنشاء العمليات الأربع: إنشاء، قراءة، تحديث، وحذف.
1. إنشاء (Create)
لإنشاء إدخال جديد في قاعدة البيانات، سنضيف مساراً للتعامل مع طلبات الإضافة:
@app.route('/add/', methods=['POST', 'GET'])
def add_entry():
if request.method == 'POST':
try:
title = request.form['title']
content = request.form['content']
conn = sqlite3.connect('database.db')
conn.execute("INSERT INTO entries (title, content) VALUES (?, ?)", (title, content))
conn.commit()
conn.close()
return redirect(url_for('show_entries'))
except Exception as e:
return f"حدث خطأ أثناء إضافة البيانات: {e}"
return render_template('add.html')
2. قراءة (Read)
لعرض جميع الإدخالات المخزنة في قاعدة البيانات:
@app.route('/entries/')
def show_entries():
conn = sqlite3.connect('database.db')
cursor = conn.execute("SELECT * FROM entries")
entries = cursor.fetchall()
conn.close()
return render_template('entries.html', entries=entries)
3. تحديث (Update)
لتحديث إدخال موجود، سنضيف مساراً يتعامل مع طلبات التحديث:
@app.route('/edit//', methods=['POST', 'GET'])
def edit_entry(id):
conn = sqlite3.connect('database.db')
if request.method == 'POST':
try:
title = request.form['title']
content = request.form['content']
conn.execute("UPDATE entries SET title=?, content=? WHERE id=?", (title, content, id))
conn.commit()
conn.close()
return redirect(url_for('show_entries'))
except Exception as e:
return f"حدث خطأ أثناء تحديث البيانات: {e}"
cursor = conn.execute("SELECT * FROM entries WHERE id=?", (id,))
entry = cursor.fetchone()
conn.close()
return render_template('edit.html', entry=entry)
4. حذف (Delete)
لحذف إدخال من قاعدة البيانات:
@app.route('/delete//')
def delete_entry(id):
try:
conn = sqlite3.connect('database.db')
conn.execute("DELETE FROM entries WHERE id=?", (id,))
conn.commit()
conn.close()
return redirect(url_for('show_entries'))
except Exception as e:
return f"حدث خطأ أثناء حذف البيانات: {e}"
الخطوة الخامسة: إنشاء قوالب HTML
لجعل التطبيق تفاعلياً وجذاباً، سنقوم بإنشاء قوالب HTML لصفحات الإضافة، العرض، والتحديث.
1. قالب إضافة إدخال جديد
<!-- templates/add.html -->
<!DOCTYPE html>
<html lang="ar">
<head>
<meta charset="UTF-8">
<title>إضافة إدخال جديد</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1 class="mt-5">إضافة إدخال جديد</h1>
<form method="POST">
<div class="form-group">
<label for="title">العنوان</label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<div class="form-group">
<label for="content">المحتوى</label>
<textarea class="form-control" id="content" name="content" rows="5" required></textarea>
</div>
<button type="submit" class="btn btn-primary">حفظ</button>
<a href="{{ url_for('show_entries') }}" class="btn btn-secondary">العودة</a>
</form>
</div>
</body>
</html>
2. قالب عرض الإدخالات
<!-- templates/entries.html -->
<!DOCTYPE html>
<html lang="ar">
<head>
<meta charset="UTF-8">
<title>قائمة الإدخالات</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1 class="mt-5">قائمة الإدخالات</h1>
<a href="{{ url_for('add_entry') }}" class="btn btn-success mb-3">إضافة إدخال جديد</a>
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>العنوان</th>
<th>المحتوى</th>
<th>الإجراءات</th>
</tr>
</thead>
<tbody>
{% for entry in entries %}
<tr>
<td>{{ entry[0] }}</td>
<td>{{ entry[1] }}</td>
<td>{{ entry[2] }}</td>
<td>
<a href="{{ url_for('edit_entry', id=entry[0]) }}" class="btn btn-warning btn-sm">تعديل</a>
<a href="{{ url_for('delete_entry', id=entry[0]) }}" class="btn btn-danger btn-sm" onclick="return confirm('هل أنت متأكد من الحذف؟');">حذف</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
3. قالب تعديل إدخال
<!-- templates/edit.html -->
<!DOCTYPE html>
<html lang="ar">
<head>
<meta charset="UTF-8">
<title>تعديل الإدخال</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1 class="mt-5">تعديل الإدخال</h1>
<form method="POST">
<div class="form-group">
<label for="title">العنوان</label>
<input type="text" class="form-control" id="title" name="title" value="{{ entry[1] }}" required>
</div>
<div class="form-group">
<label for="content">المحتوى</label>
<textarea class="form-control" id="content" name="content" rows="5" required>{{ entry[2] }}</textarea>
</div>
<button type="submit" class="btn btn-primary">تحديث</button>
<a href="{{ url_for('show_entries') }}" class="btn btn-secondary">العودة</a>
</form>
</div>
</body>
</html>
الخطوة السادسة: تحسين واجهة المستخدم باستخدام Bootstrap
لجعل واجهة المستخدم أكثر جاذبية واستجابة، سنقوم بدمج إطار عمل Bootstrap في قوالب HTML.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
لقد تم تضمين هذا الرابط في جميع قوالب HTML السابقة. يمكنك الآن استخدام فئات Bootstrap لتحسين تصميم النموذج والجداول والأزرار.
الخطوة السابعة: نشر التطبيق
بعد تطوير تطبيقك واختباره محلياً، يمكنك نشره على خادم ويب مثل Heroku أو أي خدمة استضافة تدعم Flask. تأكد من إعداد إعدادات الإنتاج بشكل صحيح، بما في ذلك إعداد متغيرات البيئة، قواعد البيانات، والأمان.
الخاتمة
في هذا الدليل، قمنا ببناء تطبيق CRUD باستخدام Flask و SQLite. هذه العمليات تشكل العمود الفقري لتطوير أي تطبيق ويب ديناميكي. يمكنك توسيع هذا المشروع بإضافة المزيد من الميزات مثل المصادقة، تحسين تصميم الواجهة، واستخدام قواعد بيانات أكثر تعقيداً مثل PostgreSQL أو MySQL.
الكود البرمجي الكامل
فيما يلي الكود الكامل لتطبيق CRUD باستخدام Flask:
from flask import Flask, render_template, request, redirect, url_for
import sqlite3
app = Flask(__name__)
def init_sqlite_db():
conn = sqlite3.connect('database.db')
print("تم الاتصال بقاعدة البيانات بنجاح")
conn.execute('''
CREATE TABLE IF NOT EXISTS entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT NOT NULL
)
''')
print("تم إنشاء الجدول بنجاح")
conn.close()
init_sqlite_db()
@app.route('/')
def index():
return redirect(url_for('show_entries'))
@app.route('/add/', methods=['POST', 'GET'])
def add_entry():
if request.method == 'POST':
try:
title = request.form['title']
content = request.form['content']
conn = sqlite3.connect('database.db')
conn.execute("INSERT INTO entries (title, content) VALUES (?, ?)", (title, content))
conn.commit()
conn.close()
return redirect(url_for('show_entries'))
except Exception as e:
return f"حدث خطأ أثناء إضافة البيانات: {e}"
return render_template('add.html')
@app.route('/entries/')
def show_entries():
conn = sqlite3.connect('database.db')
cursor = conn.execute("SELECT * FROM entries")
entries = cursor.fetchall()
conn.close()
return render_template('entries.html', entries=entries)
@app.route('/edit//', methods=['POST', 'GET'])
def edit_entry(id):
conn = sqlite3.connect('database.db')
if request.method == 'POST':
try:
title = request.form['title']
content = request.form['content']
conn.execute("UPDATE entries SET title=?, content=? WHERE id=?", (title, content, id))
conn.commit()
conn.close()
return redirect(url_for('show_entries'))
except Exception as e:
return f"حدث خطأ أثناء تحديث البيانات: {e}"
cursor = conn.execute("SELECT * FROM entries WHERE id=?", (id,))
entry = cursor.fetchone()
conn.close()
return render_template('edit.html', entry=entry)
@app.route('/delete//')
def delete_entry(id):
try:
conn = sqlite3.connect('database.db')
conn.execute("DELETE FROM entries WHERE id=?", (id,))
conn.commit()
conn.close()
return redirect(url_for('show_entries'))
except Exception as e:
return f"حدث خطأ أثناء حذف البيانات: {e}"
if __name__ == '__main__':
app.run(debug=True)
اترك تعليقاً