البرمجة

التعامل مع حقول WTForms في Flask

جدول المحتوى

التّعامل مع مكتبة WTForms ضمن إطار عمل Flask: حقول الخيارات المُتعدّدة

تُعتبر مكتبة WTForms واحدة من الأدوات الأساسية عند بناء نماذج الويب (Forms) ضمن إطار عمل Flask، حيث توفر طريقة مرنة وقوية لإنشاء وإدارة النماذج مع دعم واسع للحقول المختلفة، والتحقق من صحة البيانات المدخلة. من بين الحقول المتنوعة التي تقدمها WTForms، تبرز حقول الخيارات المُتعدّدة (Multiple Choice Fields) كأحد العناصر المهمة التي تسمح للمستخدمين باختيار أكثر من قيمة من بين عدة خيارات متاحة. هذا المقال سيُفصّل بشكل معمّق كيفية التعامل مع هذه الحقول في إطار Flask، مع التركيز على الأنواع المختلفة لهذه الحقول، كيفية تهيئتها، التحقق من صحتها، وتخصيصها بما يتناسب مع متطلبات التطبيقات المختلفة.


مقدمة عن Flask وWTForms

Flask هو إطار عمل ويب خفيف ومرن مكتوب بلغة Python، يُستخدم لتطوير تطبيقات ويب بسيطة وسريعة، مع إمكانية التوسع. من الخصائص المميزة لـ Flask هي سهولة التكامل مع مكتبات أخرى لإنشاء واجهات المستخدم والتعامل مع النماذج، وأحد أبرز هذه المكتبات هي WTForms.

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


حقول الخيارات المُتعدّدة في WTForms

مفهوم حقول الخيارات المُتعدّدة

حقول الخيارات المتعددة تسمح للمستخدم باختيار أكثر من خيار من بين مجموعة خيارات مقدمة في النموذج. هذه الحقول تختلف عن الحقول ذات الاختيار الواحد (مثل الـ RadioField)، فهي تدعم اختيار أكثر من عنصر في الوقت ذاته. أنواع حقول الخيارات المتعددة الأكثر شيوعًا في WTForms هي:

  • SelectMultipleField: لعرض قائمة منسدلة تدعم اختيار متعدد.

  • SelectMultipleField مع Checkbox: غالباً ما يتم تخصيصه لعرض مجموعة من مربعات الاختيار (Checkboxes).

  • FieldList مع BooleanField: طريقة مرنة لبناء مجموعة من الحقول التي يمكن اختيارها بشكل متعدد.


أنواع حقول الخيارات المُتعدّدة في WTForms

1. SelectMultipleField

يُستخدم SelectMultipleField عندما يحتاج النموذج إلى قائمة خيارات متعددة يمكن للمستخدم اختيار أكثر من خيار منها عن طريق الضغط على مفتاح Ctrl (في الحواسيب المكتبية) أو عبر اللمس في الهواتف.

مثال بسيط لتعريف حقل SelectMultipleField:

python
from flask_wtf import FlaskForm from wtforms import SelectMultipleField from wtforms.validators import DataRequired class PreferencesForm(FlaskForm): favorite_fruits = SelectMultipleField( 'Select your favorite fruits', choices=[('apple', 'Apple'), ('banana', 'Banana'), ('orange', 'Orange')], validators=[DataRequired()] )

في هذا المثال، المستخدم قادر على اختيار أكثر من فاكهة من بين التفاح، الموز، والبرتقال.

2. CheckboxField ضمن مجموعة (FieldList)

في حال رغبة المطور بعرض الخيارات المتعددة كمربعات اختيار (Checkboxes)، يمكن استخدام تركيبة من FieldList مع BooleanField أو استخدام مكتبة فرعية مثل WTForms-Components لتوفير CheckboxField.

طريقة تقليدية لبناء قائمة مربعات اختيار باستخدام FieldList:

python
from flask_wtf import FlaskForm from wtforms import FieldList, FormField, BooleanField, StringField class ChoiceForm(FlaskForm): choice = BooleanField() label = StringField() class PreferencesForm(FlaskForm): choices = FieldList(FormField(ChoiceForm))

لكن الاستخدام الأكثر شيوعًا لحقول الخيارات المتعددة مع مربعات الاختيار يتم عبر التخصيص اليدوي.


كيفية ربط حقول الخيارات المُتعدّدة مع واجهة HTML في Flask

لجعل الحقول تظهر بشكل صحيح للمستخدم، يجب التعامل مع القوالب (Templates) باستخدام Jinja2 في Flask. WTForms تسهل هذا التفاعل من خلال توفير واجهات جاهزة للحقول.

على سبيل المثال، لعرض SelectMultipleField في صفحة HTML:

html
<form method="POST"> {{ form.csrf_token }} <label>{{ form.favorite_fruits.label }}label> <select multiple name="{{ form.favorite_fruits.name }}"> {% for value, label in form.favorite_fruits.choices %} <option value="{{ value }}" {% if value in form.favorite_fruits.data %} selected {% endif %} >{{ label }}option> {% endfor %} select> <button type="submit">Submitbutton> form>

عند استخدام مربعات اختيار Checkbox متعددة، قد يتم بناء الحقول كالتالي:

html
<form method="POST"> {{ form.csrf_token }} <label>Choose your hobbies:label><br> {% for hobby in form.hobbies %} <input type="checkbox" name="{{ hobby.name }}" id="{{ hobby.id }}" {% if hobby.data %}checked{% endif %}> <label for="{{ hobby.id }}">{{ hobby.label.text }}label><br> {% endfor %} <button type="submit">Submitbutton> form>

التحقق من صحة بيانات حقول الخيارات المُتعدّدة

التحقق من صحة الإدخال هو جزء لا يتجزأ من WTForms. عند استخدام حقول الخيارات المتعددة، من المهم التأكد من أن القيم المدخلة صحيحة ومطابقة للقيم المسموح بها.

مثلاً، باستخدام Validator مثل DataRequired() نضمن أن المستخدم لم يترك الحقل فارغًا. في حالات أخرى، قد نستخدم Validator مخصص للتحقق من أن القيم المدخلة تقع ضمن الخيارات المتاحة فقط.

مثال للتحقق من صحة اختيار المستخدم:

python
from wtforms.validators import ValidationError def validate_choices(form, field): valid_choices = ['apple', 'banana', 'orange'] for choice in field.data: if choice not in valid_choices: raise ValidationError(f"Invalid choice: {choice}") class PreferencesForm(FlaskForm): favorite_fruits = SelectMultipleField( 'Select your favorite fruits', choices=[('apple', 'Apple'), ('banana', 'Banana'), ('orange', 'Orange')], validators=[DataRequired(), validate_choices] )

التعامل مع بيانات الحقول المتعددة بعد الإرسال

عند إرسال النموذج، تحتوي بيانات حقول الخيارات المتعددة على قائمة (List) بالقيم التي اختارها المستخدم. يمكن التعامل معها في دوال العرض (Views) في Flask بسهولة.

مثال دالة عرض تعالج نموذج الخيارات المتعددة:

python
from flask import Flask, render_template, request app = Flask(__name__) app.secret_key = 'secret-key' @app.route('/preferences', methods=['GET', 'POST']) def preferences(): form = PreferencesForm() if form.validate_on_submit(): selected_fruits = form.favorite_fruits.data # قائمة بالقيم المختارة # يمكن التعامل مع البيانات هنا، مثل تخزينها في قاعدة بيانات return f"Selected fruits: {', '.join(selected_fruits)}" return render_template('preferences.html', form=form)

تخصيص عرض حقول الخيارات المتعددة

تخصيص مظهر SelectMultipleField

يمكن تخصيص عناصر الـ HTML المرتبطة بحقل SelectMultipleField من خلال تمرير خاصيات مثل render_kw لتغيير السمات:

python
favorite_fruits = SelectMultipleField( 'Select your favorite fruits', choices=[('apple', 'Apple'), ('banana', 'Banana'), ('orange', 'Orange')], render_kw={'class': 'form-control', 'size': 5} )

هنا، ستظهر القائمة بحجم أكبر ويمكن تنسيقها باستخدام CSS.

تحويل SelectMultipleField إلى مربعات اختيار (Checkboxes)

في بعض الحالات، قد يفضل المطور عرض الخيارات كمربعات اختيار متعددة بدلاً من قائمة منسدلة. WTForms لا توفر CheckboxField متعدد بشكل مباشر، لكن يمكن بناءه عبر استخدام SelectMultipleField مع تخصيص قوالب HTML لإظهار كل خيار كمربع اختيار.

مثال على قالب يعرض SelectMultipleField كCheckboxes:

html
<form method="POST"> {{ form.csrf_token }} <label>{{ form.favorite_fruits.label }}label><br> {% for value, label in form.favorite_fruits.choices %} <input type="checkbox" name="{{ form.favorite_fruits.name }}" value="{{ value }}" {% if value in form.favorite_fruits.data %} checked {% endif %} > {{ label }}<br> {% endfor %} <button type="submit">Submitbutton> form>

استخدام FieldList لبناء قوائم اختيار ديناميكية

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

مثال عملي لبناء مجموعة من مربعات الاختيار مع FieldList:

python
from wtforms import Form, FieldList, BooleanField class HobbyForm(Form): hobby = BooleanField() class PreferencesForm(FlaskForm): hobbies = FieldList(FormField(HobbyForm), min_entries=3) # إنشاء النموذج مع ثلاثة مربعات اختيار افتراضية form = PreferencesForm() form.hobbies[0].hobby.label = 'Reading' form.hobbies[1].hobby.label = 'Traveling' form.hobbies[2].hobby.label = 'Gaming'

يتم عرض هذه المربعات في القالب عبر حلقة، ويمكن للمستخدم اختيار أي عدد منها.


تخزين بيانات الحقول المتعددة في قواعد البيانات

التعامل مع حقول الخيارات المتعددة من حيث تخزين البيانات في قواعد البيانات يحتاج إلى تصميم منطقي يراعي أن الحقل يحتوي على أكثر من قيمة. الخيارات الشائعة تشمل:

  • تخزين القيم المختارة كنص مفصول بفواصل (Comma-separated values)

  • تخزين القيم في جدول علاقات Many-to-Many (عند استخدام ORM مثل SQLAlchemy)

مثال لتخزين القيم كنص مفصول بفواصل

python
selected_fruits = form.favorite_fruits.data # قائمة fruits_string = ','.join(selected_fruits) # تحويلها إلى نص # تخزين fruits_string في قاعدة البيانات في عمود نصي

مثال باستخدام SQLAlchemy مع علاقة Many-to-Many

تصميم قاعدة بيانات يسمح بتخزين الخيارات المختارة بشكل أكثر تنظيماً:

python
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() association_table = db.Table('user_fruits', db.Column('user_id', db.Integer, db.ForeignKey('user.id')), db.Column('fruit_id', db.Integer, db.ForeignKey('fruit.id')) ) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100)) fruits = db.relationship('Fruit', secondary=association_table, back_populates='users') class Fruit(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) users = db.relationship('User', secondary=association_table, back_populates='fruits')

بهذا الشكل يمكن ربط كل مستخدم بمجموعة من الفواكه المختارة بشكل مرن دون تكرار البيانات.


تحديات وحلول شائعة في التعامل مع حقول الخيارات المتعددة

1. مشكلة اختيار الخيارات الفارغة

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

2. التعامل مع تحديث الخيارات المتاحة

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

3. التعامل مع خيارات متعددة متداخلة

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


مقارنة بين حقول الخيارات المتعددة في WTForms وطرق بديلة

استخدام SelectMultipleField مقابل Checkbox

  • SelectMultipleField: أسهل في الاستخدام والتكامل، يظهر كقائمة منسدلة تدعم اختيار متعدد، مناسب عندما يكون عدد الخيارات كبيرًا.

  • Checkboxes: أفضل من ناحية تجربة المستخدم في حال كان عدد الخيارات صغيرًا، يسمح برؤية جميع الخيارات مباشرة.

استخدام مكتبات إضافية

قد يلجأ بعض المطورين إلى استخدام مكتبات خارجية أو مكونات جافاسكريبت مثل Select2 أو Bootstrap-Select لتطوير واجهات اختيار متعددة أكثر تفاعلية وتجميلًا.


استنتاجات

حقول الخيارات المتعددة تمثل عنصراً أساسياً في بناء نماذج ويب غنية وفعالة باستخدام WTForms ضمن إطار Flask. توفر WTForms أدوات متعددة للتعامل مع هذه الحقول، سواء عبر SelectMultipleField أو الحقول المخصصة التي تعرض مربعات اختيار. الاهتمام بالتحقق من صحة البيانات، وتخصيص عرض النماذج بما يتناسب مع تجربة المستخدم، بالإضافة إلى معالجة البيانات بشكل منطقي بعد الإرسال، كلها عوامل تؤدي إلى بناء تطبيقات أكثر كفاءة وموثوقية. كما يجب الانتباه لتصميم قاعدة البيانات بما يدعم طبيعة البيانات متعددة القيم بطريقة منظمة ومرنة.

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