البرمجة

تعديل علاقات One-to-Many في Flask

جدول المحتوى

تعديل العناصر في علاقات One-to-Many باستخدام Flask و SQLite

تعتبر علاقات One-to-Many من أكثر العلاقات شيوعًا في قواعد البيانات العلائقية، حيث يرتبط عنصر واحد بعدد من العناصر الأخرى، مثل العلاقة بين مؤلف وعدد الكتب التي كتبها. في بيئة تطوير الويب، وعند بناء تطبيقات باستخدام إطار العمل Flask ومحرك قاعدة البيانات SQLite، يصبح التعامل مع هذه العلاقات وتنفيذ عمليات تعديل على العناصر التابعة أمرًا أساسيًا لضمان مرونة التطبيق وديناميكيته.

في هذا المقال، سنغطي بشكل معمق كيفية تعديل عناصر ضمن علاقة One-to-Many باستخدام Flask و SQLite، مع التركيز على إعداد قاعدة البيانات، تصميم النماذج (Models) بطريقة صحيحة باستخدام SQLAlchemy، ثم كيفية إنشاء طرق (Routes) تستقبل البيانات من المستخدمين وتعدلها بشكل آمن وفعال في قاعدة البيانات.


1. مقدمة عن علاقات One-to-Many في قواعد البيانات

علاقة One-to-Many تعني وجود سجل واحد في جدول مرتبط بعدد من السجلات في جدول آخر. على سبيل المثال:

  • جدول المؤلفين (Authors)

  • جدول الكتب (Books)

كل مؤلف يمكن أن يكون مرتبطًا بعدد من الكتب، لكن كل كتاب مرتبط بمؤلف واحد فقط.

تمثيل علاقة One-to-Many في قواعد البيانات

في قاعدة البيانات، يتم تمثيل هذه العلاقة عادة بإضافة عمود مفتاح أجنبي (Foreign Key) في الجدول الذي يمثل الطرف “Many” يشير إلى سجل في الجدول “One”.

على سبيل المثال، جدول الكتب يحتوي على عمود author_id يشير إلى السجل في جدول المؤلفين.


2. إعداد بيئة العمل: Flask مع SQLite و SQLAlchemy

لتنفيذ عمليات تعديل على عناصر علاقة One-to-Many، يجب أولاً تجهيز بيئة العمل. يعتمد Flask على امتداد SQLAlchemy لإدارة قواعد البيانات بشكل سلس.

الخطوات الأساسية:

  1. تثبيت المكتبات المطلوبة:

    • Flask

    • Flask-SQLAlchemy

bash
pip install Flask Flask-SQLAlchemy
  1. تهيئة التطبيق وإعداد قاعدة البيانات:

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

3. تصميم النماذج (Models) لعلاقة One-to-Many

في مثالنا، سنقوم بتعريف نموذجين: Author و Book.

python
class Author(db.Model): __tablename__ = 'authors' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) # العلاقة مع الكتب books = db.relationship('Book', backref='author', lazy=True) class Book(db.Model): __tablename__ = 'books' id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(200), nullable=False) author_id = db.Column(db.Integer, db.ForeignKey('authors.id'), nullable=False)
  • خاصية books في نموذج Author تمثل العلاقة مع مجموعة الكتب.

  • في نموذج Book، author_id هو المفتاح الأجنبي الذي يشير إلى المؤلف.


4. إنشاء قاعدة البيانات والجداول

بعد تعريف النماذج، يمكن إنشاء الجداول في قاعدة البيانات:

python
with app.app_context(): db.create_all()

هذه العملية تنشئ جداول authors و books في ملف library.db.


5. إضافة بيانات تجريبية للعلاقات

لإنشاء علاقة One-to-Many، يجب أولاً إضافة مؤلف ومن ثم عدة كتب مرتبطة به.

python
with app.app_context(): # إنشاء مؤلف جديد author = Author(name="جورج أورويل") db.session.add(author) db.session.commit() # إضافة كتب مرتبطة بالمؤلف book1 = Book(title="1984", author_id=author.id) book2 = Book(title="مزرعة الحيوان", author_id=author.id) db.session.add_all([book1, book2]) db.session.commit()

6. تعديل عناصر ضمن علاقة One-to-Many

التعديل قد يشمل تعديل بيانات المؤلف أو تعديل بيانات الكتب المرتبطة به. يمكن التعديل بشكل فردي لكل كتاب، أو تعديل علاقة الكتاب بالمؤلف (مثل نقل كتاب لمؤلف آخر).

6.1 تعديل بيانات كتاب معين

تعديل عنوان كتاب معين يمكن أن يتم عبر استرجاع الكتاب من قاعدة البيانات ثم تحديثه.

python
with app.app_context(): book = Book.query.filter_by(id=1).first() if book: book.title = "1984 - الطبعة الجديدة" db.session.commit()

6.2 تعديل المؤلف لكتاب معين (تغيير العلاقة)

في بعض الأحيان، نحتاج إلى تغيير المؤلف المرتبط بكتاب. مثلًا، نقل كتاب من مؤلف إلى آخر.

python
with app.app_context(): book = Book.query.filter_by(id=1).first() new_author = Author.query.filter_by(name="إرنست همنغواي").first() if book and new_author: book.author_id = new_author.id db.session.commit()

6.3 تعديل بيانات المؤلف مع تعديل بيانات الكتب المرتبطة

عند تعديل مؤلف مع تعديل بيانات الكتب المرتبطة به، يمكن التعامل مع كل جزء على حدة.

python
with app.app_context(): author = Author.query.filter_by(id=1).first() if author: author.name = "جورج أورويل المعدل" for book in author.books: book.title = book.title + " (نسخة معدلة)" db.session.commit()

7. بناء واجهة تعديل البيانات في Flask

عادةً، يحتاج التطبيق إلى واجهة (Form) تتيح للمستخدم تعديل بيانات المؤلف والكتب المرتبطة. يمكن استخدام Flask-WTF لبناء هذه النماذج، لكن هنا سنوضح الفكرة الأساسية باستخدام HTML وطرق Flask.

7.1 مثال على تعديل كتاب

python
from flask import request, render_template, redirect, url_for @app.route('/book/edit/', methods=['GET', 'POST']) def edit_book(book_id): book = Book.query.get_or_404(book_id) if request.method == 'POST': new_title = request.form.get('title') new_author_id = request.form.get('author_id') if new_title: book.title = new_title if new_author_id: book.author_id = int(new_author_id) db.session.commit() return redirect(url_for('list_books')) authors = Author.query.all() return render_template('edit_book.html', book=book, authors=authors)

7.2 مثال على نموذج تعديل كتاب (edit_book.html)

html
<form method="POST"> <label>عنوان الكتاب:label> <input type="text" name="title" value="{{ book.title }}"> <label>المؤلف:label> <select name="author_id"> {% for author in authors %} <option value="{{ author.id }}" {% if author.id == book.author_id %}selected{% endif %}>{{ author.name }}option> {% endfor %} select> <button type="submit">تحديثbutton> form>

8. التعامل مع تعديلات متعددة في عناصر العلاقة

في حالات متقدمة، قد يحتاج المستخدم لتعديل عدة كتب مرتبطة بمؤلف معين دفعة واحدة، أو حتى تعديل المؤلف نفسه.

8.1 تعديل متعدد باستخدام Flask

يمكن تصميم صفحة تعرض المؤلف وكتب المرتبطة به في نموذج واحد، ثم يتم إرسال البيانات دفعة واحدة لتحديثها.

python
@app.route('/author/edit/', methods=['GET', 'POST']) def edit_author_with_books(author_id): author = Author.query.get_or_404(author_id) if request.method == 'POST': # تحديث اسم المؤلف new_name = request.form.get('name') if new_name: author.name = new_name # تحديث الكتب for book in author.books: new_title = request.form.get(f'title_{book.id}') if new_title: book.title = new_title db.session.commit() return redirect(url_for('list_authors')) return render_template('edit_author_with_books.html', author=author)

8.2 نموذج HTML لتعديل المؤلف والكتب المرتبطة به

html
<form method="POST"> <label>اسم المؤلف:label> <input type="text" name="name" value="{{ author.name }}"> <h3>الكتب المرتبطة:h3> {% for book in author.books %} <label>عنوان الكتاب {{ loop.index }}:label> <input type="text" name="title_{{ book.id }}" value="{{ book.title }}"> {% endfor %} <button type="submit">تحديثbutton> form>

9. ممارسات وأمان التعامل مع التعديلات في علاقات One-to-Many

9.1 التحقق من صحة البيانات

من المهم التحقق من صحة البيانات القادمة من المستخدم لضمان سلامة قاعدة البيانات، مثل التأكد من أن عناوين الكتب ليست فارغة، وأن معرف المؤلف موجود في قاعدة البيانات.

9.2 حماية ضد الهجمات (مثل CSRF)

استخدام أدوات مثل Flask-WTF يسهل إضافة حماية ضد الهجمات عبر نماذج الويب. أيضًا يجب التحقق من صلاحيات المستخدم قبل السماح بالتعديل.

9.3 استخدام المعاملات (Transactions)

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

python
try: # تعديل متعدد db.session.commit() except: db.session.rollback() raise

10. مقارنة الأداء بين SQLite وأنظمة قواعد البيانات الأخرى

SQLite خيار ممتاز للتطبيقات الصغيرة والمتوسطة، لكن مع زيادة حجم البيانات وتعقيد العلاقات وكمية التعديلات المتزامنة، قد يحتاج التطبيق إلى الانتقال إلى أنظمة قواعد بيانات أكثر قوة مثل PostgreSQL أو MySQL التي توفر أدوات متقدمة لإدارة العلاقات والتزامن.


11. جدول يوضح الفروقات الأساسية بين SQLAlchemy وطرق التعامل اليدوي مع SQL في تعديل العلاقات

الخاصية SQLAlchemy ORM SQL اليدوي (Raw SQL)
سهولة كتابة الأكواد عالية، بفضل النماذج والعلاقات أقل، يتطلب كتابة جمل SQL مفصلة
الحماية من حقن SQL مدعومة تلقائياً يتطلب استخدام الاستعلامات المحضرة
التعامل مع العلاقات مبسط، بفضل العلاقات المعرفة مسبقًا معقد، يتطلب جمل JOIN يدوية
قراءة الكود وصيانته أسهل، بفضل التجريد أصعب، خاصة مع استعلامات معقدة
دعم التعديل الجماعي مدعوم مع إدارة الجلسات يحتاج كتابة استعلامات تحديث متعددة

12. خلاصة

تُعد عملية تعديل العناصر في علاقات One-to-Many باستخدام Flask و SQLite من العمليات التي تبرز أهمية التصميم الجيد للنماذج والعلاقات في قاعدة البيانات، بالإضافة إلى التعامل المرن مع طلبات التعديل من خلال واجهات المستخدم. من خلال استخدام SQLAlchemy، يمكن تبسيط العمليات المعقدة التي تتعلق بتعديل السجلات المرتبطة، مع ضمان سلامة البيانات وأمانها.

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


المراجع