flask_wtforms التّحقّق من مُدخلات المُستخدم باستخدام مكتبة WTForms على تطبيقات Flask


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

مُقدّمة:

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

flask-wtf-02.png

كيف تعمل مكتبة WTForms ؟

من المهم أن تدرك بأنّ استخدام مكتبة WTForms يكون على عدّة مراحل:

  • إنشاء صنف Class خاص ليُمثّل النّموذج
  • تقديم النّموذج باستخدام إطار العمل Flask إلى ملف HTML
  • عرض الحقول على صفحة HTML
  • الوصول إلى المُدخلات بعد إرسال النّموذج من طرف المُستخدم

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

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

تعريف الصّنف المسؤول عن النّموذج

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

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

from flask_wtf import FlaskForm

from wtforms import TextField, PasswordField
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username = TextField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])

نسترد أولا الصّنف FlaskForm الذي تحدّثنا عنه سابقا في الدّرس السّابق من إضافة Flask-WTF، بعدها نقوم باستيراد TextField الذي يُعبّر عن حقل نصي في نماذج HTML، أي بمعنى آخر، الوسم <input> مع الخاصيّة type=text، ونسترد كذلك الصّنف الذي يُسمى PasswordField الذي يعتبر حقلا لكلمة المرور أي الوسم <input> مع الخاصيّة type=password في لغة HTML، ولاحظ بأنّنا نسترد هذه الأصناف التّي تٌعبّر عن الحقول من مكتبة WTForms وليس من إضافة Flask-WTF.
بعدها نقوم باستيراد المُصَادِق DataRequired من الوحدة validators المتواجدة بالمكتبة WTForms، سيُمكّننا هذا المُصادق من التّحقق من أنّ الحقل لا يحمل قيمة فارغة عند إرسال البيانات (بمعنى آخر، سيُصبح الحقل مطلوبا).

بعد استيراد ما نحتاج إليه، سنقوم بإنشاء صنف باسم LoginForm ليُمثّل النّموذج الخاص بتسجيل الدّخول، لاحظ بأنّ هذا الصّنف يرث من الصّنف FlaskForm الذي قمنا باستيراده من إضافة Flask-WTF.

وبما أنّ النّموذج سيحتوي حقلين فقط، حقل لاسم المُستخدم وحقل آخر لكلمة المرور، ثمّ زر لتأكيد وإرسال البيانات Submit button، فقد قمنا بتعريفهما داخل الصّنف، إذ عرّفنا أولا حقل اسم المُستخدم بتعريف مُتغيّر باسم username ليكون كائنا من الصّنف TextField مع تمرير مُعاملين، الأول عبارة عن سلسلة نصيّة تُمثّل لصيقة الحقل أو Field Label، أمّا المُعامل الآخر فعبارة عن قائمة بالمُصادقين، وفي حالتنا فإنّ القائمة تحتوي على مُصادق واحد فقط وهو DataRequired() لجعل الحقل مطلوبا (أي منع المُستخدم من إرسال الحقل فارغا).
نقوم بنفس الشيء مع حقل كلمة المرور، مع جعل الكائن من الصّنف PasswordField لتظهر مُدخلات المُستخدم على شكل نجمات عوضا عن نص واضح، كما أنّنا نُشير إلى أنّه حقل مطلوب كذلك عبر تمرير DataRequired كعنصر من قائمة إلى المُعامل validators.
بالنّسبة لزر إرسال البيانات فسنقوم بكتابته مُباشرة بلغة HTML في ملفّ القالب.

أين توضع الشّيفرة المسؤولة عن النّماذج؟

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

لكن من المُفضّل دائما اتّباع أفضل المُمارسات Best practices وهي ما يقوم به الجميع والمنصوح به لتوفير طريقة تطوير موحّدة ولتسهيل قراءة شيفرتك على الآخرين، وأفضل ممارسة في ما يتعلّق بالأصناف المسؤولة عن نماذج HTML هي بوضع الشّيفرة المسؤولة عن النّماذج في ملف باسم forms.py داخل مُجلّد التّطبيق لتوفير تقسيم منظّم للشّيفرة.

تقديم النّموذج من المُوجّه إلى قالب HTML

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

لتبسيط الأمور، سأجمع الصّنف LoginForm و شيفرة التّطبيق في نفس الملف، وسيكون التّطبيق بسيطا ليفهمه الجميع.
الشّيفرة الكاملة ستكون كالتّالي (قمت بفصل شيفرة النّموذج وشيفرة التّطبيق بفاصل صغير):

from flask_wtf import FlaskForm

from wtforms import TextField, PasswordField
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username = TextField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])

# ---------------------------

from flask import Flask, render_template

app = Flask(__name__)

app.config['SECRET_KEY'] = 'T\x1f\x85\x9b\xfe^\x0f\x14\x9f\xa3x\xa4\xb5\x92\xbe'

@app.route('/', methods=['GET', 'POST'])
def form():
    form = LoginForm()
    if form.validate_on_submit():   
        # Handle received data
        pass

    return render_template('form.html', form = form)

if __name__ == "__main__":
    app.run(debug=True)

كما تُلاحظ أعلاه، قمنا بإنشاء تطبيق بسيط نسترد فيه كلا من الصّنف Flask والدّالة render_template، ثمّ ننشئ الكائن app وبعدها نقوم بتحديد مفتاح سري لتتمكّن مكتبة WTForms من توليد حقل خفي للحماية من هجمات CSRF، وبعدها نقوم بتعريف المُوجّه ونُشغّل الخادوم في آخر سطرين.

أهم شيء في التّطبيق هو الموجّه الرّئيسي ومُحتوى الدّالة form التي سنقوم من خلالها بتقديم ومُعالجة النّموذج وبياناته:

@app.route('/', methods=['GET', 'POST'])
def form():
    form = LoginForm()
    if form.validate_on_submit():
        # Handle received data
        pass

    render_template('form.html', form=form)

أولا نقوم بتحديد أنواع الطّلبات التّي سيقبلها المُوجّه بتمرير قائمة إلى المعامل methods لإخبار فلاسك بأنّ هذا المُوجّه سيستقبل كلا من طلبات GET التّي ستُقدّم النّموذج وطلبات POST التّي ستستقبل ومن ثمّ نُعالجها البيانات.
بعدها نقوم بتعريف الكائن form من الصّنف LoginForm، يُمكنك الآن تجاهل الشّرط if form.validate_on_submit() لأنّه يهتم بمُعالجة البيانات والمُصادقة عليها ولن نقوم بُمعالجتها حاليا لكن عليك أن تعلم بأنّ المُعالجة ستتمّ في مكان التّعليق Handle received data، في الأخير نقوم بتقديم الملفّ form.html مع تمرير الكائن form لنتمكّن من الوصول إليه في القالب.

خاتمة

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

 





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


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



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن