البرمجة

إنشاء مدونة بفلاسـك وSQLAlchemy

استخدام SQLAlchemy في فلاسـك لإنشاء مدونة مع علاقات Many-to-Many

في عالم تطوير الويب، تُعتبر فلاسـك (Flask) واحدة من أشهر وأبسط أُطر العمل لبناء تطبيقات ويب باستخدام لغة البرمجة بايثون. تتميز فلاسـك بخفة وزنها ومرونتها، مما يجعلها مناسبة جداً لتطوير تطبيقات متنوعة، من المواقع البسيطة إلى الأنظمة المعقدة. مع ذلك، عندما يتعلق الأمر بالتعامل مع قواعد البيانات، يحتاج المطور إلى استخدام أدوات قوية ومرنة لإدارة العمليات الخاصة بإنشاء، قراءة، تحديث، وحذف البيانات (CRUD).

واحدة من هذه الأدوات هي SQLAlchemy، وهي مكتبة ORM (Object Relational Mapper) تسمح بالتعامل مع قواعد البيانات بطريقة كائنية، وتوفر طبقة تجريدية عن التعامل المباشر مع SQL. في هذا المقال، سنتناول بالتفصيل كيفية استخدام SQLAlchemy في تطبيق فلاسـك لإنشاء مدونة متكاملة، مع التركيز على بناء علاقات Many-to-Many بين الكيانات المختلفة.


مقدمة حول Flask و SQLAlchemy

فلاسـك (Flask)

فلاسـك هو إطار عمل ويب صغير وخفيف الوزن مبني على بايثون، يُستخدم لإنشاء تطبيقات ويب بسهولة ومرونة عالية. هو إطار عمل “ميكرو” بمعنى أنه لا يتطلب الكثير من الإعدادات المسبقة أو الاعتماد على مكتبات خارجية، لكنه يدعم التوسعات عبر مكتبات إضافية حسب الحاجة.

SQLAlchemy

SQLAlchemy هي مكتبة ORM تسمح للمطورين بإنشاء نماذج كائنية (Classes) تمثل الجداول في قواعد البيانات، بحيث يمكن إجراء العمليات على البيانات باستخدام البرمجة الكائنية بدلًا من كتابة استعلامات SQL يدوية. توفر SQLAlchemy دعمًا لأنواع مختلفة من قواعد البيانات، مثل SQLite، MySQL، PostgreSQL، وغيرها.


لماذا استخدام علاقات Many-to-Many في المدونة؟

في نظام المدونة التقليدي، توجد عدة كيانات (Entities) مثل المستخدمون (Users)، المقالات (Posts)، والتصنيفات (Tags). التصنيفات غالبًا ما تُستخدم لتصنيف المقالات بحيث يمكن للمقال الواحد أن يحتوي على عدة تصنيفات، وفي نفس الوقت يمكن لكل تصنيف أن يرتبط بعدة مقالات. هذا النوع من العلاقات يُعرف بعلاقة Many-to-Many.

علاقات Many-to-Many تعني وجود ارتباط متعدد الاتجاهات بين صفوف جدولين، وتتطلب جدول وسيط (Association Table) لتمثيل هذه العلاقة داخل قاعدة البيانات.


تصميم قاعدة البيانات للمدونة

الكيانات الأساسية

  • User: يمثل المستخدم الذي يكتب المقالات.

  • Post: يمثل المقال أو التدوينة نفسها.

  • Tag: يمثل التصنيفات أو الوسوم المرتبطة بالمقالات.

العلاقة بين الكيانات

  • مستخدم واحد يمكنه كتابة عدة مقالات (One-to-Many).

  • مقال واحد يمكن أن يحتوي على عدة تصنيفات.

  • تصنيف واحد يمكن أن يرتبط بعدة مقالات (Many-to-Many).


إنشاء المشروع وضبط البيئة

أولاً، نقوم بإنشاء بيئة تطويرية جديدة وتثبيت المكتبات اللازمة:

bash
python -m venv venv source venv/bin/activate # على ويندوز: venv\Scripts\activate pip install Flask SQLAlchemy Flask-Migrate
  • Flask: إطار العمل الأساسي.

  • SQLAlchemy: المكتبة التي ستستخدم ORM.

  • Flask-Migrate: أداة لإدارة ترحيل قواعد البيانات.


إعداد تطبيق Flask مع SQLAlchemy

في ملف app.py، نقوم بإعداد التطبيق وقاعدة البيانات:

python
from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db)

إنشاء النماذج Models مع علاقة Many-to-Many

لإنشاء علاقة Many-to-Many، نحتاج إلى جدول وسيط.

1. إنشاء جدول الوسيط (Association Table)

python
post_tags = db.Table('post_tags', db.Column('post_id', db.Integer, db.ForeignKey('post.id'), primary_key=True), db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True) )
  • هذا الجدول لا يحتوي على كائن Model مستقل، بل يُستخدم فقط كجدول وسيط لربط المقالات بالتصنيفات.

  • يحتوي على عمودين: post_id و tag_id، وكلاهما مفاتيح خارجية تشير إلى الجداول الأساسية.

2. تعريف نموذج المستخدم User

python
class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) posts = db.relationship('Post', backref='author', lazy=True)
  • يحتوي المستخدم على مجموعة من المقالات.

  • العلاقة بين المستخدم والمقال هي One-to-Many.

3. تعريف نموذج المقال Post

python
class Post(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(150), nullable=False) content = db.Column(db.Text, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) tags = db.relationship('Tag', secondary=post_tags, lazy='subquery', backref=db.backref('posts', lazy=True))
  • يحتوي المقال على عنوان، محتوى، ورابط إلى المستخدم الذي كتبه.

  • يحتوي أيضًا على علاقة Many-to-Many مع التصنيفات عبر جدول post_tags.

4. تعريف نموذج التصنيف Tag

python
class Tag(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), unique=True, nullable=False)

شرح العلاقة Many-to-Many بين Post و Tag

في نموذج Post، يتم استخدام db.relationship مع المعامل secondary ليشير إلى جدول post_tags الوسيط. هذا يتيح للمطور التعامل مع التصنيفات المرتبطة بالمقال كقائمة Python عادية، مما يسهل إضافة أو إزالة التصنيفات.

مثال على العلاقة:

  • عند إنشاء مقال جديد، يمكن ربطه بتصنيفات موجودة أو جديدة.

  • عند جلب مقال من قاعدة البيانات، يمكن الوصول إلى كل تصنيفات المقال بسهولة.


استخدام النماذج في التطبيق: إنشاء وإدارة البيانات

إنشاء مستخدم جديد

python
new_user = User(username='ahmed', email='[email protected]') db.session.add(new_user) db.session.commit()

إنشاء تصنيفات جديدة

python
tag_python = Tag(name='Python') tag_flask = Tag(name='Flask') db.session.add_all([tag_python, tag_flask]) db.session.commit()

إنشاء مقال وربطه بتصنيفات ومستخدم

python
new_post = Post(title='مقدمة في Flask', content='محتوى المقال هنا...', author=new_user) new_post.tags.append(tag_python) new_post.tags.append(tag_flask) db.session.add(new_post) db.session.commit()

استعلام البيانات مع علاقات Many-to-Many

جلب جميع المقالات مع التصنيفات

python
posts = Post.query.all() for post in posts: print(f"المقال: {post.title}") print("التصنيفات:") for tag in post.tags: print(f"- {tag.name}")

جلب جميع المقالات التي تحتوي على تصنيف معين

python
flask_tag = Tag.query.filter_by(name='Flask').first() for post in flask_tag.posts: print(post.title)

إدارة ترحيل قاعدة البيانات مع Flask-Migrate

لضمان سهولة تحديث قاعدة البيانات عند إضافة أو تعديل النماذج، يمكن استخدام Flask-Migrate.

خطوات العمل:

  1. إنشاء مجلد الترحيلات:

bash
flask db init
  1. إنشاء ملف ترحيل جديد يحتوي على التغييرات:

bash
flask db migrate -m "Initial migration"
  1. تطبيق الترحيل على قاعدة البيانات:

bash
flask db upgrade

جدول يوضح نماذج البيانات والعلاقات

الكيان الحقول الأساسية نوع العلاقة الكيان المرتبط نوع العلاقة في جهة الكيان المرتبط
User id, username, email One-to-Many (User -> Post) Post Many-to-One (Post -> User)
Post id, title, content, user_id Many-to-Many (Post <-> Tag) Tag Many-to-Many (Tag <-> Post)
Tag id, name Many-to-Many (Tag <-> Post) Post Many-to-Many (Post <-> Tag)

مزايا استخدام SQLAlchemy مع Flask في تطبيقات العلاقات المعقدة

  • المرونة: يمكن تعريف نماذج معقدة وعلاقات متعددة بسهولة دون الحاجة لكتابة استعلامات SQL معقدة.

  • سهولة الصيانة: التغييرات في الهيكل تكون مركزة في نماذج البيانات.

  • دعم ترحيل قاعدة البيانات: باستخدام Flask-Migrate يمكن تحديث الهيكل بمرونة دون فقدان البيانات.

  • كفاءة التطوير: توفير الوقت والجهد في بناء التطبيقات المعقدة مثل المدونات.


الخلاصة

تعتبر علاقة Many-to-Many من العلاقات المهمة التي تُستخدم بشكل واسع في بناء نظم المعلومات مثل المدونات، حيث يكون للمقالات تصنيفات متعددة والعكس صحيح. باستخدام Flask مع SQLAlchemy يمكن تصميم هذا النوع من العلاقات بطريقة بسيطة وواضحة، تضمن سهولة في التطوير والصيانة، ومرونة في إدارة البيانات.

الخطوات التي تم شرحها تغطي إنشاء الجداول الأساسية، وإنشاء جدول وسيط لتمثيل العلاقة، وكيفية استخدام ORM لإدارة العلاقة من خلال نماذج الكائنات، بالإضافة إلى كيفية استعلام وإضافة البيانات بشكل متقدم مع دعم ترحيل قاعدة البيانات.

هذا النهج يجعل بناء مدونة متكاملة أمراً منظماً وقابلاً للتوسع المستقبلي بسهولة.