اذهب إلى المحتوى

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


عبدالهادي الديوري

مُقدّمة:

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

36465-Flask-WTF-4.png

الحقول ومكوّنات النّماذج

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

حقل النّص القصير وكلمة المرور.

سبق وأن استخدمنا حقلي input من نوع text و password، وهذان الحقلان يُسمّيان TextField و PasswordField على التّوالي في مكتبة WTForms.
ويُمكننا تعريف كل حقل كما يلي:

text = TextField('Text Label')
password = PasswordField('Password')

وبالطّبع فسنحتاج إلى استيرادها من مكتبة WTForms :

from wtforms import TextField, PasswordField

ولتقديمها في ملفّ HTML يُمكنك الاستعانة بمُحرّك القوالب Jinja وعرض كل حقل كالآتي:

{{ form.text }}

{{ form.password }}

وللوصول إلى وسم label كل حقل:

{{ form.text.label }}

{{ form.password.label }}

وللوصول إلى الأخطاء المُنتجة من المُصادقين فيُمكنك القيام بالتّأكّد أولا من أنها موجودة في field.errors مع استبدال field باسم الحقل ثمّ الدّوران على الأخطاء بطريقة مُشابهة لما يلي:

{% if form.text.errors %}
    {% for error in form.text.errors %}
         {{ error }}
    {% endfor %}
{% endif %}
{% if form.password.errors %}
    {% for error in form.password.errors %}
         {{ error }}
    {% endfor %}
{% endif %}

حقل النّص الطّويل (مساحة النّص، Text Area)

تعرّفنا على كيفيّة إنشاء حقل صغير ليتمكّن المُستخدم من إرسال سلاسل نصيّة قصيرة (مثل اسم المُستخدم أو بريده الإلكتروني)، وحان الوقت للتّعرف على كيفيّة إنشاء حقل نصي أكبر للنّصوص الطّويلة مثل المقالات والتّعليقات، وهذا الحقل معروف في لغة HTML بوسم TextArea.

يُمكنك إنشاء حقل نصّي طويل باستخدام مكتبة WTForms عن
طريق الصّنف TextAreaField، وبالطّبع فلا بد من استيراده بنفس الطّريقة، لنقوم كالعادة بتعريف مُتغيّر في الصّنف الذي يسترد من الصّنف FlaskForm الذي نسترده في حالتنا من إضافة Flask-WTF، والمثال التّالي عبارة عن نموذج لتمكين المُستخدم من إرسال مقال عن طريق إرسال عنوانه ومُحتواه، والمُحتوى في هذه الحالة هو الحقل الذي سيكون طويلا:

from flask_wtf import FlaskForm
from wtforms import TextField, TextAreaField

class PostForm(FlaskForm):
    title = TextField('Title')
    content = TextAreaField('Content')

وكما تُلاحظ أعلاه، فالأمر مُشابه تماما لما سبق، ولو أردت إضافة مُصادق فالطرّيقة هي نفسها، استرد المُصادق ثمّ مرّره كعنصر من قائمة إلى المُعامل validators.

وبنفس الطّريقة السّابقة، نقوم بإنشاء كائن من الصّنف PostForm ونقوم بتمريره إلى ملف HTML.

def form():
    form = PostForm()
    if form.validate_on_submit():   
        title = form.title.data
        content = form.content.data
    return render_template('form.html', form=form)

وفي ملفّ HTML نقوم بتقديم النّموذج بنفس الطّريقة المذكورة في الدّرس السّابق.
وستُلاحظ بأنّنا نستطيع الوصول إلى محتويات الحقول بعد إرسال النّموذج بشكل طبيعي:

form.title.data
form.content.data

حقل الأعداد الصّحيحة

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

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

إليك مثالا على كيفيّة إنشاء نموذج يحمل حقل الأعداد الصّحيحة:

from flask_wtf import FlaskForm
from wtforms import IntegerField

class AgeForm(FlaskForm):
    age = IntegerField('Integer')

إذا حاولت إرسال بيانات غير الأعداد الصّحيحة فستحصل على خطأ ولن يُرسل النّموذج إلى الخادوم، وبالتّالي ستتجنّب بعضا من مُحاولات التّخريب.

حقل التّاريخ

حقل التّاريخ DateField نوع آخر من الحقول التّي تُوفّرها لنا مكتبة WTForms والذي نستعمله للحصول على المزيد من المرونة عند منح المُستخدم إمكانيّة إدخال تاريخ إلى قاعدة البيانات، ويُمكّننا الحقل من استقبال بيانات تكون على شكل تاريخ، أمّا إن لم يكن المُدخل على شكل تاريخ فسيحصل المُستخدم على خطأ ولن تمر المُدخلات إلى الخادوم، ويترك لك الحقل حريّة تحديد شكل التّاريخ فمثلا يمكنك تحديد التّاريخ على شكل يوم-شهر-سنة أو سنة/شهر/سنة أو أي شكل تحدّده مع الفصل بينها بأي فاصل تُريده، وأي بيانات تُرسل عن طريق ذلك لن تمرّ إلّا لو طابقت المعايير المُحدّدة.

وطريقة العمل بسيطة جدّا، إذ تقوم بتعريف مُتغيّر ليُمثّل الحقل DateField الذي نقوم باستيراده بنفس الطّريقة المذكورة سابقا:

from flask_wtf import FlaskForm
from wtforms import DateField

class AgeForm(FlaskForm):
    age = DateField('Date')

وطريقة تقديمه بصفحة HTML لا تتغيّر كذلك.

وإن أردت تغيير شكل التّاريخ إلى صيغة أخرى مثل يوم/شهر/سنة فالطّريقة بسيطة جدّا، إذ تُوفّر شكلا للتّاريخ المقبول أثناء تعريف الحقل DateField عبر تمريره إلى المُعامل format، والقيمة الافتراضيّة له هي كالآتي:

'%Y-%m-%d'

Y تعني السّنة بصيغتها الكاملة (مثل 1998، 2010، 2016 …).
m تعني الشّهر.
D تعني اليوم.
وبالتّالي فالصّيغة التّالية ستكون مقبولة:

2016-10-13

أمّا التّاريخ بالصّيغة التّاليّة فغير مقبولة:

13-10-2016

ولتوفير صيغتك الخاصّة، فتستطيع ذلك عن طريق تمرير قيمة إلى المُعامل format لتعويض الصّيغة الافتراضية.
والتّالي مثال على كيفيّة إنشاء حقل يقبل تاريخا على شكل يوم/شهر/سنة:

date = DateField('Date', format='%d/%m/%Y')

وبالتّالي فعند إدخال التّاريخ على الشّكل التّالي فسيُقبل ويُرسل إلى الخادوم دون مشاكل:

13/10/2016

إن أردت تجاهل أحد مُكونات التّاريخ فيُمكنك ذلك، فمثلا يُمكنك الاعتماد على السّنة والشّهر فقط:

date = DateField('Date', format='%Y-%m')

وبالتّالي فسيكون التّاريخ المقبول كما يلي:

2016-10

مُعالجة التّاريخ بعد استقباله

عندما يُدخل المُستخدم التّاريخ ثمّ يصل إلى الخادوم، فتستطيع الوصول إليه كما يلي:

form.date.data

وهذه هي الطّريقة التّقليديّة، ولكن، لأنّ WTForms تقوم بإنشاء تاريخ من النوع datetime.date في لغة بايثون، فسنستطيع الوصول إلى المعلومات الأخرى بسهولة.
فمثلا، للوصول إلى السّنة في التّاريخ المُرسل، تستطيع بسهولة إضافة year إلى ما سبق:

form.date.data.year

وبنفس الطّريقة، تستطيع الوصول إلى الشّهر:

form.date.data.month

واليوم:

form.date.data.day

وكأي كائن من النّوع datetime.date فستتمكّن من الوصول إلى جميع المعلومات الأخرى المُتعلّقة بالتّاريخ.

مُلاحظة:
الحقل DateField يقوم بإنشاء حقل نص قصير عادي، إن أردت استخدام الحقل الجديد في HTML5 بالخاصيّة type="date"، فتستطيع استيراده من الحزمة html5 في مكتبة WTForms كما يلي:

from wtforms.fields.html5 import DateField

إن أنشأت حقلا من هذا الصّنف فستحصل على ما يلي:

<input id="date" name="date" type="date">

لاحظ بأنّ قيمة الخاصيّة type قد تغيّرت من text إلى date وبالتّالي فستتمكّن من توفير تجربة استخدام أفضل عبر تمكين مُستخدمي تطبيقك من اختيار التّاريخ باستخدام الأداة المتوفّرة في لغة HTML5.

خاتمة

تعرّفنا في هذا الدّرس على بعض من المكوّنات الشّائعة في مكتبة WTForms التّي يُمكنك الاستفادة منها في تطبيقاتك لتوفير حماية أفضل، وبما أنّ هناك العديد من الحقول في لغة HTML، فسنتطرّق إلى ما تبقّى في الدّرس التّالي.


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...